Scippy

SCIP

Solving Constraint Integer Programs

primal.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file primal.c
26 * @ingroup OTHER_CFILES
27 * @brief methods for collecting primal CIP solutions and primal informations
28 * @author Tobias Achterberg
29 */
30
31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32
33#include <assert.h>
34
35#include "scip/def.h"
36#include "scip/set.h"
37#include "scip/stat.h"
38#include "scip/visual.h"
39#include "scip/event.h"
40#include "scip/lp.h"
41#include "scip/lpexact.h"
42#include "scip/var.h"
43#include "scip/prob.h"
44#include "scip/sol.h"
45#include "scip/primal.h"
46#include "scip/tree.h"
47#include "scip/reopt.h"
48#include "scip/disp.h"
49#include "scip/struct_event.h"
50#include "scip/struct_lpexact.h"
51#include "scip/pub_message.h"
52#include "scip/pub_var.h"
53#include "scip/scip_message.h"
55
56
57/*
58 * memory growing methods for dynamically allocated arrays
59 */
60
61/** ensures, that sols array can store at least num entries */
62static
64 SCIP_PRIMAL* primal, /**< primal data */
65 SCIP_SET* set, /**< global SCIP settings */
66 int num /**< minimum number of entries to store */
67 )
68{
69 assert(primal->nsols <= primal->solssize);
70
71 if( num > primal->solssize )
72 {
73 int newsize;
74
75 newsize = SCIPsetCalcMemGrowSize(set, num);
76 SCIP_ALLOC( BMSreallocMemoryArray(&primal->sols, newsize) );
77 primal->solssize = newsize;
78 }
79 assert(num <= primal->solssize);
80
81 return SCIP_OKAY;
82}
83
84/** ensures, that partialsols array can store at least num entries */
85static
87 SCIP_PRIMAL* primal, /**< primal data */
88 SCIP_SET* set, /**< global SCIP settings */
89 int num /**< minimum number of entries to store */
90 )
91{
92 assert(primal->npartialsols <= primal->partialsolssize);
93
94 if( num > primal->partialsolssize )
95 {
96 int newsize;
97
98 newsize = SCIPsetCalcMemGrowSize(set, num);
99 newsize = MIN(newsize, set->limit_maxorigsol);
100
101 SCIP_ALLOC( BMSreallocMemoryArray(&primal->partialsols, newsize) );
102 primal->partialsolssize = newsize;
103 }
104 assert(num <= primal->partialsolssize);
105
106 return SCIP_OKAY;
107}
108
109/** ensures, that existingsols array can store at least num entries */
110static
112 SCIP_PRIMAL* primal, /**< primal data */
113 SCIP_SET* set, /**< global SCIP settings */
114 int num /**< minimum number of entries to store */
115 )
116{
117 assert(primal->nexistingsols <= primal->existingsolssize);
118
119 if( num > primal->existingsolssize )
120 {
121 int newsize;
122
123 newsize = SCIPsetCalcMemGrowSize(set, num);
124 SCIP_ALLOC( BMSreallocMemoryArray(&primal->existingsols, newsize) );
125 primal->existingsolssize = newsize;
126 }
127 assert(num <= primal->existingsolssize);
128
129 return SCIP_OKAY;
130}
131
132/** creates primal data */
134 SCIP_PRIMAL** primal /**< pointer to primal data */
135 )
136{
137 assert(primal != NULL);
138
139 SCIP_ALLOC( BMSallocMemory(primal) );
140 (*primal)->sols = NULL;
141 (*primal)->partialsols = NULL;
142 (*primal)->existingsols = NULL;
143 (*primal)->currentsol = NULL;
144 (*primal)->primalray = NULL;
145 (*primal)->solssize = 0;
146 (*primal)->partialsolssize = 0;
147 (*primal)->nsols = 0;
148 (*primal)->npartialsols = 0;
149 (*primal)->existingsolssize = 0;
150 (*primal)->nexistingsols = 0;
151 (*primal)->nsolsfound = 0;
152 (*primal)->nlimsolsfound = 0;
153 (*primal)->nbestsolsfound = 0;
154 (*primal)->nlimbestsolsfound = 0;
155 (*primal)->upperbound = SCIP_INVALID;
156 (*primal)->upperboundexact = NULL;
157 (*primal)->cutoffbound = SCIP_INVALID;
158 (*primal)->updateviolations = TRUE;
159 (*primal)->cutoffboundexact = NULL;
160
161 return SCIP_OKAY;
162}
163
164/** frees primal data */
166 SCIP_PRIMAL** primal, /**< pointer to primal data */
167 BMS_BLKMEM* blkmem /**< block memory */
168 )
169{
170 assert(primal != NULL);
171 assert(*primal != NULL);
172
173 SCIP_CALL( SCIPprimalClear(*primal, blkmem) );
174
175 BMSfreeMemoryArrayNull(&(*primal)->sols);
176 BMSfreeMemoryArrayNull(&(*primal)->partialsols);
177 BMSfreeMemoryArrayNull(&(*primal)->existingsols);
178 if( (*primal)->cutoffboundexact != NULL )
179 {
180 SCIPrationalFreeBlock(blkmem, &(*primal)->upperboundexact);
181 SCIPrationalFreeBlock(blkmem, &(*primal)->cutoffboundexact);
182 }
183
184 BMSfreeMemory(primal);
185
186 return SCIP_OKAY;
187}
188
189/** clears primal data */
191 SCIP_PRIMAL* primal, /**< pointer to primal data */
192 BMS_BLKMEM* blkmem /**< block memory */
193 )
194{
195 int s;
196
197 assert(primal != NULL);
198
199 /* free temporary solution for storing current solution */
200 if( primal->currentsol != NULL )
201 {
202 SCIP_CALL( SCIPsolFree(&primal->currentsol, blkmem, primal) );
203 }
204
205 /* free solution for storing primal ray */
206 if( primal->primalray != NULL )
207 {
208 SCIP_CALL( SCIPsolFree(&primal->primalray, blkmem, primal) );
209 }
210
211 /* free feasible primal CIP solutions */
212 for( s = 0; s < primal->nsols; ++s )
213 {
214 SCIP_CALL( SCIPsolFree(&primal->sols[s], blkmem, primal) );
215 }
216
217 /* free partial CIP solutions */
218 for( s = 0; s < primal->npartialsols; ++s )
219 {
220 SCIP_CALL( SCIPsolFree(&primal->partialsols[s], blkmem, primal) );
221 }
222 assert(primal->nexistingsols == 0);
223
224 primal->currentsol = NULL;
225 primal->primalray = NULL;
226 primal->nsols = 0;
227 primal->nsolsfound = 0;
228 primal->npartialsols = 0;
229 primal->nlimsolsfound = 0;
230 primal->nbestsolsfound = 0;
231 primal->nlimbestsolsfound = 0;
232 primal->upperbound = SCIP_INVALID;
233 primal->cutoffbound = SCIP_INVALID;
234 primal->updateviolations = TRUE;
235
236 return SCIP_OKAY;
237}
238
239/** sorts primal solutions by objective value */
240static
242 SCIP_PRIMAL* primal, /**< primal data */
243 SCIP_SET* set, /**< global SCIP settings */
244 SCIP_PROB* origprob, /**< original problem */
245 SCIP_PROB* transprob /**< transformed problem */
246 )
247{
248 int i;
249
250 for( i = 1; i < primal->nsols; ++i )
251 {
252 SCIP_SOL* sol;
253 SCIP_Real objval;
254 int j;
255
256 sol = primal->sols[i];
257 objval = SCIPsolGetObj(sol, set, transprob, origprob);
258 for( j = i; j > 0 && objval < SCIPsolGetObj(primal->sols[j-1], set, transprob, origprob); --j )
259 primal->sols[j] = primal->sols[j-1];
260 primal->sols[j] = sol;
261 }
262
263 return;
264}
265
266/** sets the cutoff bound in primal data and in LP solver */
267static
269 SCIP_PRIMAL* primal, /**< primal data */
270 BMS_BLKMEM* blkmem, /**< block memory */
271 SCIP_SET* set, /**< global SCIP settings */
272 SCIP_STAT* stat, /**< problem statistics data */
273 SCIP_PROB* prob, /**< problem data */
274 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
275 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
276 SCIP_TREE* tree, /**< branch and bound tree */
277 SCIP_REOPT* reopt, /**< reoptimization data structure */
278 SCIP_LP* lp, /**< current LP data */
279 SCIP_Real cutoffbound /**< new cutoff bound */
280 )
281{
282 assert(primal != NULL);
283 assert(cutoffbound <= SCIPsetInfinity(set));
284 assert(primal->upperbound == SCIP_INVALID || SCIPsetIsLE(set, cutoffbound, primal->upperbound)); /*lint !e777*/
285 assert(!SCIPtreeInRepropagation(tree));
286
287 SCIPsetDebugMsg(set, "changing cutoff bound from %g to %g\n", primal->cutoffbound, cutoffbound);
288
289 primal->cutoffbound = MIN(cutoffbound, primal->upperbound); /* get rid of numerical issues */
290
291 /* possibly update the exact cutoffbound */
292 if( set->exact_enable )
293 {
294 SCIP_RATIONAL* tmp;
295
296 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
297 SCIPrationalSetReal(tmp, primal->cutoffbound);
298 if( SCIPrationalIsGT(primal->cutoffboundexact, tmp) )
300 SCIPrationalFreeBuffer(set->buffer, &tmp);
301 }
302
303 /* set cut off value in LP solver */
304 SCIP_CALL( SCIPlpSetCutoffbound(lp, set, prob, primal->cutoffbound) );
305
306 /* cut off leaves of the tree */
307 SCIP_CALL( SCIPtreeCutoff(tree, reopt, blkmem, set, stat, eventqueue, eventfilter, lp, primal->cutoffbound) );
308
309 return SCIP_OKAY;
310}
311
312/** sets the cutoff bound in primal data and in LP solver */
313static
315 SCIP_PRIMAL* primal, /**< primal data */
316 BMS_BLKMEM* blkmem, /**< block memory */
317 SCIP_SET* set, /**< global SCIP settings */
318 SCIP_STAT* stat, /**< problem statistics data */
319 SCIP_PROB* prob, /**< problem data */
320 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
321 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
322 SCIP_TREE* tree, /**< branch and bound tree */
323 SCIP_REOPT* reopt, /**< reoptimization data structure */
324 SCIP_LP* lp, /**< current LP data */
325 SCIP_RATIONAL* cutoffbound /**< new cutoff bound */
326 )
327{
328 assert(primal != NULL);
329 assert(SCIPrationalIsLEReal(cutoffbound, SCIPsetInfinity(set)));
330 assert(!SCIPtreeInRepropagation(tree));
331 assert(set->exact_enable);
332
333 SCIPrationalDebugMessage("changing exact cutoff bound from %q to %q\n", primal->cutoffboundexact, cutoffbound);
334
335 SCIPrationalMin(primal->cutoffboundexact, cutoffbound, primal->upperboundexact); /* get rid of numerical issues */
337
338 /* set cut off value in LP solver */
339 SCIP_CALL( SCIPlpSetCutoffbound(lp, set, prob, primal->cutoffbound) );
340
341 /* cut off leaves of the tree */
342 SCIP_CALL( SCIPtreeCutoff(tree, reopt, blkmem, set, stat, eventqueue, eventfilter, lp, primal->cutoffbound) );
343
344 return SCIP_OKAY;
345}
346
347/** sets the cutoff bound in primal data and in LP solver */
349 SCIP_PRIMAL* primal, /**< primal data */
350 BMS_BLKMEM* blkmem, /**< block memory */
351 SCIP_SET* set, /**< global SCIP settings */
352 SCIP_STAT* stat, /**< problem statistics data */
353 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
354 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
355 SCIP_PROB* transprob, /**< transformed problem data */
356 SCIP_PROB* origprob, /**< original problem data */
357 SCIP_TREE* tree, /**< branch and bound tree */
358 SCIP_REOPT* reopt, /**< reoptimization data structure */
359 SCIP_LP* lp, /**< current LP data */
360 SCIP_Real cutoffbound, /**< new cutoff bound */
361 SCIP_Bool useforobjlimit /**< should the cutoff bound be used to update the objective limit, if
362 * better? */
363 )
364{
365 assert(primal != NULL);
366 assert(cutoffbound <= SCIPsetInfinity(set));
367 assert(cutoffbound <= primal->upperbound);
368 assert(transprob != NULL);
369 assert(origprob != NULL);
370
371 if( cutoffbound < primal->cutoffbound )
372 {
373 if( useforobjlimit )
374 {
375 SCIP_Real objval;
376
377 objval = SCIPprobExternObjval(transprob, origprob, set, cutoffbound);
378
379 if( objval < SCIPprobGetObjlim(origprob, set) )
380 {
381 SCIPsetDebugMsg(set, "changing cutoff bound from %g to %g changes objective limit from %g to %g\n",
382 primal->cutoffbound, cutoffbound, SCIPprobGetObjlim(origprob, set), objval);
383 SCIPprobSetObjlim(origprob, objval);
384 SCIPprobSetObjlim(transprob, objval);
385 }
386 }
387
388 /* update cutoff bound */
389 SCIP_CALL( primalSetCutoffbound(primal, blkmem, set, stat, transprob, eventqueue, eventfilter, tree, reopt, lp, cutoffbound) );
390 }
391 else if( cutoffbound > primal->cutoffbound )
392 {
393 SCIPerrorMessage("invalid increase in cutoff bound\n");
394 return SCIP_INVALIDDATA;
395 }
396
397 return SCIP_OKAY;
398}
399
400/** sets upper bound in primal data and in LP solver */
401static
403 SCIP_PRIMAL* primal, /**< primal data */
404 BMS_BLKMEM* blkmem, /**< block memory */
405 SCIP_SET* set, /**< global SCIP settings */
406 SCIP_STAT* stat, /**< problem statistics data */
407 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
408 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
409 SCIP_PROB* prob, /**< transformed problem after presolve */
410 SCIP_TREE* tree, /**< branch and bound tree */
411 SCIP_REOPT* reopt, /**< reoptimization data structure */
412 SCIP_LP* lp, /**< current LP data */
413 SCIP_Real upperbound /**< new upper bound */
414 )
415{
416 SCIP_Real cutoffbound;
417
418 assert(primal != NULL);
419 assert(stat != NULL);
420 assert(upperbound <= SCIPsetInfinity(set));
421 assert(upperbound <= primal->upperbound || stat->nnodes == 0);
422
423 SCIPsetDebugMsg(set, "changing upper bound from %g to %g\n", primal->upperbound, upperbound);
424
425 primal->upperbound = upperbound;
426
427 /* if objective value is always integral, the cutoff bound can be reduced to nearly the previous integer number */
428 if( SCIPprobIsObjIntegral(prob) && !SCIPsetIsInfinity(set, upperbound) )
429 {
430 SCIP_Real delta;
431
433
434 cutoffbound = SCIPsetFeasCeil(set, upperbound) - (1.0 - delta);
435 cutoffbound = MIN(cutoffbound, upperbound); /* SCIPsetFeasCeil() can increase bound by almost 1.0 due to numerics
436 * and very large upperbound value */
437 }
438 else
439 cutoffbound = upperbound;
440
441 /* update cutoff bound */
442 if( cutoffbound < primal->cutoffbound )
443 {
444 SCIP_CALL( primalSetCutoffbound(primal, blkmem, set, stat, prob, eventqueue, eventfilter, tree, reopt, lp, cutoffbound) );
445 }
446
447 /* update upper bound in visualization output */
448 if( SCIPtreeGetCurrentDepth(tree) >= 0 )
449 {
450 SCIPvisualUpperbound(stat->visual, set, stat, primal->upperbound);
451 }
452
453 return SCIP_OKAY;
454}
455
456/** sets upper bound in primal data and in LP solver */
457static
459 SCIP_PRIMAL* primal, /**< primal data */
460 BMS_BLKMEM* blkmem, /**< block memory */
461 SCIP_SET* set, /**< global SCIP settings */
462 SCIP_STAT* stat, /**< problem statistics data */
463 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
464 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
465 SCIP_PROB* prob, /**< transformed problem after presolve */
466 SCIP_TREE* tree, /**< branch and bound tree */
467 SCIP_REOPT* reopt, /**< reoptimization data structure */
468 SCIP_LP* lp, /**< current LP data */
469 SCIP_RATIONAL* upperbound /**< new upper bound */
470 )
471{
472 SCIP_RATIONAL* cutoffbound;
473
474 assert(primal != NULL);
475 assert(stat != NULL);
476 assert(set->exact_enable);
477 assert(SCIPrationalIsLEReal(upperbound, SCIPsetInfinity(set)));
478 assert(SCIPrationalIsLEReal(upperbound, primal->upperbound) || stat->nnodes == 0);
479
480 SCIPrationalDebugMessage("changing upper bound from %q to %q\n", primal->upperboundexact, upperbound);
481
482 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &cutoffbound) );
483 SCIPrationalSetRational(primal->upperboundexact, upperbound);
485
486 /* if objective value is always integral, the cutoff bound can be reduced to nearly the previous integer number */
487 if( SCIPprobIsObjIntegral(prob) && !SCIPrationalIsInfinity(upperbound) )
488 {
489 SCIP_Real delta;
490
492
494 SCIPrationalDiffReal(cutoffbound, cutoffbound, 1.0);
495 SCIPrationalAddReal(cutoffbound, cutoffbound, delta);
496 }
497 else
498 SCIPrationalSetRational(cutoffbound, upperbound);
499
500 /* update cutoff bound */
501 if( SCIPrationalIsLT(cutoffbound, primal->cutoffboundexact) )
502 {
503 SCIP_CALL( primalSetCutoffboundExact(primal, blkmem, set, stat, prob, eventqueue, eventfilter, tree, reopt, lp, cutoffbound) );
504 }
505
506 /* update upper bound in visualization output */
507 if( SCIPtreeGetCurrentDepth(tree) >= 0 )
508 {
509 SCIPvisualUpperbound(stat->visual, set, stat, primal->upperbound);
510 }
511
512 SCIPrationalFreeBuffer(set->buffer, &cutoffbound);
513
514 return SCIP_OKAY;
515}
516
517/** sets upper bound in primal data and in LP solver */
519 SCIP_PRIMAL* primal, /**< primal data */
520 BMS_BLKMEM* blkmem, /**< block memory */
521 SCIP_SET* set, /**< global SCIP settings */
522 SCIP_STAT* stat, /**< problem statistics data */
523 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
524 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
525 SCIP_PROB* prob, /**< transformed problem after presolve */
526 SCIP_TREE* tree, /**< branch and bound tree */
527 SCIP_REOPT* reopt, /**< reoptimization data structure */
528 SCIP_LP* lp, /**< current LP data */
529 SCIP_Real upperbound /**< new upper bound */
530 )
531{
532 assert(primal != NULL);
533 assert(upperbound <= SCIPsetInfinity(set));
534
535 if( upperbound < primal->upperbound )
536 {
537 /* update primal bound */
538 SCIP_CALL( primalSetUpperbound(primal, blkmem, set, stat, eventqueue, eventfilter, prob, tree, reopt, lp, upperbound) );
539 }
540 else if( upperbound > primal->upperbound )
541 {
542 SCIPerrorMessage("invalid increase in upper bound\n");
543 return SCIP_INVALIDDATA;
544 }
545
546 return SCIP_OKAY;
547}
548
549/** updates upper bound and cutoff bound in primal data after a tightening of the problem's objective limit */
551 SCIP_PRIMAL* primal, /**< primal data */
552 BMS_BLKMEM* blkmem, /**< block memory */
553 SCIP_SET* set, /**< global SCIP settings */
554 SCIP_STAT* stat, /**< problem statistics data */
555 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
556 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
557 SCIP_PROB* transprob, /**< transformed problem data */
558 SCIP_PROB* origprob, /**< original problem data */
559 SCIP_TREE* tree, /**< branch and bound tree */
560 SCIP_REOPT* reopt, /**< reoptimization data structure */
561 SCIP_LP* lp /**< current LP data */
562 )
563{
564 SCIP_Real objlimit;
565 SCIP_Real inf;
566
567 assert(primal != NULL);
568
569 /* get internal objective limit */
570 objlimit = SCIPprobInternObjval(transprob, origprob, set, SCIPprobGetObjlim(origprob, set));
571 inf = SCIPsetInfinity(set);
572 objlimit = MIN(objlimit, inf);
573
574 /* update the cutoff bound */
575 if( objlimit < primal->cutoffbound )
576 {
577 SCIP_CALL( primalSetCutoffbound(primal, blkmem, set, stat, transprob, eventqueue, eventfilter, tree, reopt, lp, objlimit) );
578 }
579
580 /* set new upper bound (and decrease cutoff bound, if objective value is always integral) */
581 if( objlimit < primal->upperbound )
582 {
583 SCIP_CALL( primalSetUpperbound(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, tree, reopt, lp, objlimit) );
584 }
585
586 return SCIP_OKAY;
587}
588
589/** recalculates upper bound and cutoff bound in primal data after a change of the problem's objective offset */
591 SCIP_PRIMAL* primal, /**< primal data */
592 BMS_BLKMEM* blkmem, /**< block memory */
593 SCIP_SET* set, /**< global SCIP settings */
594 SCIP_STAT* stat, /**< problem statistics data */
595 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
596 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
597 SCIP_PROB* transprob, /**< tranformed problem data */
598 SCIP_PROB* origprob, /**< original problem data */
599 SCIP_TREE* tree, /**< branch and bound tree */
600 SCIP_REOPT* reopt, /**< reoptimization data structure */
601 SCIP_LP* lp /**< current LP data */
602 )
603{
604 SCIP_Real upperbound;
605 SCIP_Real inf;
606
607 assert(primal != NULL);
609
610 /* recalculate internal objective limit */
611 upperbound = SCIPprobInternObjval(transprob, origprob, set, SCIPprobGetObjlim(origprob, set));
612 inf = SCIPsetInfinity(set);
613 upperbound = MIN(upperbound, inf);
614
615 /* resort current primal solutions */
616 sortPrimalSols(primal, set, origprob, transprob);
617
618 /* compare objective limit to currently best solution */
619 if( primal->nsols > 0 )
620 {
621 SCIP_Real obj;
622
623 assert(SCIPsolIsOriginal(primal->sols[0]));
624 obj = SCIPsolGetObj(primal->sols[0], set, transprob, origprob);
625
626 upperbound = MIN(upperbound, obj);
627 }
628
629 /* invalidate old upper bound */
630 SCIP_CALL( primalSetUpperbound(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, tree, reopt, lp, SCIPsetInfinity(set)) );
631
632 /* reset the cutoff bound
633 *
634 * @note we might need to relax the bound since in presolving the objective correction of an
635 * aggregation is still in progress
636 */
637 SCIP_CALL( primalSetCutoffbound(primal, blkmem, set, stat, transprob, eventqueue, eventfilter, tree, reopt, lp, upperbound) );
638
639 /* set new upper bound (and decrease cutoff bound, if objective value is always integral) */
640 SCIP_CALL( primalSetUpperbound(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, tree, reopt, lp, upperbound) );
641
642 return SCIP_OKAY;
643}
644
645/** recalculates upper bound and cutoff bound in primal data after a change of the problem's objective offset */
647 SCIP_PRIMAL* primal, /**< primal data */
648 BMS_BLKMEM* blkmem, /**< block memory */
649 SCIP_SET* set, /**< global SCIP settings */
650 SCIP_STAT* stat, /**< problem statistics data */
651 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
652 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
653 SCIP_PROB* transprob, /**< tranformed problem data */
654 SCIP_PROB* origprob, /**< original problem data */
655 SCIP_TREE* tree, /**< branch and bound tree */
656 SCIP_REOPT* reopt, /**< reoptimization data structure */
657 SCIP_LP* lp /**< current LP data */
658 )
659{
660 SCIP_RATIONAL* upperbound;
661 SCIP_RATIONAL* tmp;
662 SCIP_RATIONAL* inf;
663
664 assert(primal != NULL);
666
667 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
668 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &upperbound) );
669 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &inf) );
670
671 /* recalculate internal objective limit */
674 SCIPprobInternObjvalExact(transprob, origprob, set, tmp, upperbound);
675
676 /* resort current primal solutions */
677 sortPrimalSols(primal, set, origprob, transprob);
678
679 /* compare objective limit to currently best solution */
680 if( primal->nsols > 0 )
681 {
682 SCIP_RATIONAL* obj;
683
684 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &obj) );
685
686 assert(SCIPsolIsOriginal(primal->sols[0]));
687
688 if( !SCIPsolIsExact(primal->sols[0]) )
689 SCIPrationalSetReal(obj, SCIPsolGetObj(primal->sols[0], set, transprob, origprob));
690 else
691 SCIPsolGetObjExact(primal->sols[0], set, transprob, origprob, obj);
692
693 SCIPrationalMin(upperbound, upperbound, obj);
694
695 SCIPrationalFreeBuffer(set->buffer, &obj);
696 }
697
698 /* invalidate old upper bound */
699 SCIP_CALL( primalSetUpperboundExact(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, tree, reopt, lp, inf) );
700
701 /* reset the cutoff bound
702 *
703 * @note we might need to relax the bound since in presolving the objective correction of an
704 * aggregation is still in progress
705 */
706 SCIP_CALL( primalSetCutoffboundExact(primal, blkmem, set, stat, transprob, eventqueue, eventfilter, tree, reopt, lp, upperbound) );
707
708 /* set new upper bound (and decrease cutoff bound, if objective value is always integral) */
709 SCIP_CALL( primalSetUpperboundExact(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, tree, reopt, lp, upperbound) );
710
711 SCIPrationalFreeBuffer(set->buffer, &inf);
712 SCIPrationalFreeBuffer(set->buffer, &upperbound);
713 SCIPrationalFreeBuffer(set->buffer, &tmp);
714
715 return SCIP_OKAY;
716}
717
718/** adds additional objective offset in original space to all existing solution (in original space) */
720 SCIP_PRIMAL* primal, /**< primal data */
721 SCIP_SET* set, /**< global SCIP settings */
722 SCIP_Real addval /**< additional objective offset in original space */
723 )
724{
725 int i;
726
727 assert(primal != NULL);
728 assert(set != NULL);
729 assert(!set->exact_enable);
731
732#ifndef NDEBUG
733 assert(primal->nsols == 0 || SCIPsolGetOrigin(primal->sols[0]) == SCIP_SOLORIGIN_ORIGINAL);
734
735 /* check current order of primal solutions */
736 for( i = 1; i < primal->nsols; ++i )
737 {
738 assert(SCIPsolGetOrigin(primal->sols[i]) == SCIP_SOLORIGIN_ORIGINAL);
739 assert(SCIPsetIsLE(set, SCIPsolGetOrigObj(primal->sols[i-1]), SCIPsolGetOrigObj(primal->sols[i])));
740 }
741#endif
742
743 /* check current order of primal solutions */
744 for( i = 0; i < primal->nexistingsols; ++i )
745 {
746 assert(primal->existingsols[i] != NULL);
747 SCIPsolOrigAddObjval(primal->existingsols[i], addval);
748 }
749}
750
751/** adds additional objective offset in original space to all existing solution (in original space) */
753 SCIP_PRIMAL* primal, /**< primal data */
754 SCIP_SET* set, /**< global SCIP settings */
755 SCIP_RATIONAL* addval /**< additional objective offset in original space */
756 )
757{
758 int i;
759
760 assert(primal != NULL);
761 assert(set != NULL);
762 assert(set->exact_enable);
764
765#ifndef NDEBUG
766 assert(primal->nsols == 0 || SCIPsolGetOrigin(primal->sols[0]) == SCIP_SOLORIGIN_ORIGINAL);
767
768 /* check current order of primal solutions */
769 for( i = 1; i < primal->nsols; ++i )
770 {
771 assert(SCIPsolGetOrigin(primal->sols[i]) == SCIP_SOLORIGIN_ORIGINAL);
772 assert(SCIPsetIsLE(set, SCIPsolGetOrigObj(primal->sols[i-1]), SCIPsolGetOrigObj(primal->sols[i])));
773 }
774#endif
775
776 /* check current order of primal solutions */
777 for( i = 0; i < primal->nexistingsols; ++i )
778 {
779 assert(primal->existingsols[i] != NULL);
780 SCIPsolOrigAddObjvalExact(primal->existingsols[i], addval);
781 }
782}
783
784/** returns whether the current primal bound is justified with a feasible primal solution; if not, the primal bound
785 * was set from the user as objective limit
786 */
788 SCIP_PRIMAL* primal, /**< primal data */
789 SCIP_SET* set, /**< global SCIP settings */
790 SCIP_PROB* transprob, /**< tranformed problem data */
791 SCIP_PROB* origprob /**< original problem data */
792 )
793{
794 assert(primal != NULL);
795
796 return (primal->nsols > 0 && SCIPsetIsEQ(set, primal->upperbound, SCIPsolGetObj(primal->sols[0], set, transprob, origprob)));
797}
798
799/** returns the primal ray thats proves unboundedness */
801 SCIP_PRIMAL* primal /**< primal data */
802 )
803{
804 assert(primal != NULL);
805
806 return primal->primalray;
807}
808
809/** update the primal ray thats proves unboundedness */
811 SCIP_PRIMAL* primal, /**< primal data */
812 SCIP_SET* set, /**< global SCIP settings */
813 SCIP_STAT* stat, /**< dynamic SCIP statistics */
814 SCIP_SOL* primalray, /**< the new primal ray */
815 BMS_BLKMEM* blkmem /**< block memory */
816 )
817{
818 assert(primal != NULL);
819 assert(set != NULL);
820 assert(stat != NULL);
821 assert(primalray != NULL);
822 assert(blkmem != NULL);
823
824 /* clear previously stored primal ray, if any */
825 if( primal->primalray != NULL )
826 {
827 SCIP_CALL( SCIPsolFree(&primal->primalray, blkmem, primal) );
828 }
829
830 assert(primal->primalray == NULL);
831
832 SCIP_CALL( SCIPsolCopy(&primal->primalray, blkmem, set, stat, primal, primalray) );
833
834 return SCIP_OKAY;
835}
836
837/** forward declaration; adds exact primal solution to solution storage at given position */
838static
840 SCIP_PRIMAL* primal, /**< primal data */
841 BMS_BLKMEM* blkmem, /**< block memory */
842 SCIP_SET* set, /**< global SCIP settings */
843 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
844 SCIP_STAT* stat, /**< problem statistics data */
845 SCIP_PROB* origprob, /**< original problem */
846 SCIP_PROB* transprob, /**< transformed problem after presolve */
847 SCIP_TREE* tree, /**< branch and bound tree */
848 SCIP_REOPT* reopt, /**< reoptimization data structure */
849 SCIP_LPEXACT* lpexact, /**< current LP data */
850 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
851 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
852 SCIP_SOL** solptr, /**< pointer to primal CIP solution */
853 int insertpos, /**< position in solution storage to add solution to */
854 SCIP_Bool replace /**< should the solution at insertpos be replaced by the new solution? */
855 );
856
857/** adds primal solution to solution storage at given position */
858static
860 SCIP_PRIMAL* primal, /**< primal data */
861 BMS_BLKMEM* blkmem, /**< block memory */
862 SCIP_SET* set, /**< global SCIP settings */
863 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
864 SCIP_STAT* stat, /**< problem statistics data */
865 SCIP_PROB* origprob, /**< original problem */
866 SCIP_PROB* transprob, /**< transformed problem after presolve */
867 SCIP_TREE* tree, /**< branch and bound tree */
868 SCIP_REOPT* reopt, /**< reoptimization data structure */
869 SCIP_LP* lp, /**< current LP data */
870 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
871 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
872 SCIP_SOL** solptr, /**< pointer to primal CIP solution */
873 int insertpos, /**< position in solution storage to add solution to */
874 SCIP_Bool replace /**< should the solution at insertpos be replaced by the new solution? */
875 )
876{
877 SCIP_SOL* sol;
878 SCIP_EVENT event;
879 SCIP_Real obj;
880 int pos;
881
882 assert(primal != NULL);
883 assert(set != NULL);
884 assert(solptr != NULL);
885 assert(stat != NULL);
886 assert(transprob != NULL);
887 assert(origprob != NULL);
888 assert(0 <= insertpos && insertpos < set->limit_maxsol);
889 assert(tree == NULL || !SCIPtreeInRepropagation(tree));
890
891 sol = *solptr;
892 assert(sol != NULL);
893
894 /* if the solution is added during presolving and it is not defined on original variables,
895 * presolving operations will destroy its validity, so we retransform it to the original space
896 */
897 if( set->stage < SCIP_STAGE_PRESOLVED && !SCIPsolIsOriginal(sol) )
898 {
899 SCIP_Bool hasinfval;
900
901 SCIP_CALL( SCIPsolUnlink(sol, set, transprob) );
902 SCIP_CALL( SCIPsolRetransform(sol, set, stat, origprob, transprob, &hasinfval) );
903 }
904
905 obj = SCIPsolGetObj(sol, set, transprob, origprob);
906
907 if( set->exact_enable )
908 {
909 if( !SCIPsolIsExact(sol) )
910 {
912 SCIP_CALL( SCIPsolMakeExact(sol, blkmem, set, stat, origprob) );
913 else
914 SCIP_CALL( SCIPsolMakeExact(sol, blkmem, set, stat, transprob) );
915
916 SCIP_CALL( primalAddSolExact(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
917 tree, reopt, lp->lpexact, eventqueue, eventfilter, solptr, insertpos, replace) );
918
919 return SCIP_OKAY;
920 }
921 else
922 {
923 SCIP_RATIONAL* objexact;
924
925 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &objexact) );
926
927 SCIPsolGetObjExact(sol, set, transprob, origprob, objexact);
928
929 if( SCIPrationalIsLT(objexact, primal->upperboundexact) )
930 {
931 SCIP_CALL( primalSetUpperboundExact(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, tree, reopt, lp, objexact) );
932 }
933
934 SCIPrationalFreeBuffer(set->buffer, &objexact);
935 }
936 }
937
938 SCIPsetDebugMsg(set, "insert primal solution %p with obj %g at position %d (replace=%u):\n",
939 (void*)sol, obj, insertpos, replace);
940
941 /* make sure that the primal bound is at least the lower bound */
943 {
945 {
946 SCIPmessagePrintWarning(messagehdlr, "Dual bound %g is larger than the objective of the primal solution %g. The solution might not be optimal.\n",
947 SCIPprobExternObjval(transprob, origprob, set, SCIPgetLowerbound(set->scip)), SCIPprobExternObjval(transprob, origprob, set, obj));
948 }
949 else
950 {
951 SCIPmessagePrintWarning(messagehdlr, "Dual bound %g is smaller than the objective of the primal solution %g. The solution might not be optimal.\n",
952 SCIPprobExternObjval(transprob, origprob, set, SCIPgetLowerbound(set->scip)), SCIPprobExternObjval(transprob, origprob, set, obj));
953 }
954
955#ifdef WITH_DEBUG_SOLUTION
956 /* check for missed debugsol cutoff */
957 if( SCIPdebugSolIsEnabled(set->scip) )
958 {
959 SCIP_SOL* debugsol;
960
961 SCIPdebugGetSol(set->scip, &debugsol);
962
964 assert(SCIPsetIsFeasLE(set, SCIPgetDualbound(set->scip), SCIPsolGetOrigObj(debugsol)));
965 else
966 assert(SCIPsetIsFeasGE(set, SCIPgetDualbound(set->scip), SCIPsolGetOrigObj(debugsol)));
967 }
968#endif
969 }
970
971 SCIPdebug( SCIP_CALL( SCIPsolPrint(sol, set, messagehdlr, stat, transprob, NULL, NULL, FALSE, FALSE) ) );
972
973#ifdef SCIP_DISABLED_CODE
974 /* this is not a valid debug check, but can be used to track down numerical troubles */
975#ifndef NDEBUG
976 /* check solution again completely
977 * it fail for different reasons:
978 * - in the LP solver, the feasibility tolerance is a relative measure against the row's norm
979 * - in SCIP, the feasibility tolerance is a relative measure against the row's rhs/lhs
980 * - the rhs/lhs of a row might drastically change during presolving when variables are fixed or (multi-)aggregated
981 */
982 if( !SCIPsolIsOriginal(sol) )
983 {
984 SCIP_Bool feasible;
985
986 SCIP_CALL( SCIPsolCheck(sol, set, messagehdlr, blkmem, stat, transprob, TRUE, TRUE, TRUE, TRUE, &feasible) );
987
988 if( !feasible )
989 {
990 SCIPerrorMessage("infeasible solution accepted:\n");
991 SCIP_CALL( SCIPsolPrint(sol, set, messagehdlr, stat, origprob, transprob, NULL, FALSE, FALSE) );
992 }
993 assert(feasible);
994 }
995#endif
996#endif
997
998 /* completely fill the solution's own value array to unlink it from the LP or pseudo solution */
999 SCIP_CALL( SCIPsolUnlink(sol, set, transprob) );
1000
1001 /* allocate memory for solution storage */
1002 SCIP_CALL( ensureSolsSize(primal, set, set->limit_maxsol) );
1003
1004 /* if set->limit_maxsol was decreased in the meantime, free all solutions exceeding the limit */
1005 for( pos = set->limit_maxsol; pos < primal->nsols; ++pos )
1006 {
1007 SCIP_CALL( SCIPsolFree(&primal->sols[pos], blkmem, primal) );
1008 }
1009 primal->nsols = MIN(primal->nsols, set->limit_maxsol);
1010
1011 /* if the solution should replace an existing one, free this solution, otherwise,
1012 * free the last solution if the solution storage is full;
1013 */
1014 if( replace )
1015 {
1016 SCIP_CALL( SCIPsolTransform(primal->sols[insertpos], solptr, blkmem, set, primal) );
1017 sol = primal->sols[insertpos];
1018 }
1019 else
1020 {
1021 if( primal->nsols == set->limit_maxsol ) /* cppcheck-suppress knownConditionTrueFalse */
1022 {
1023 SCIP_CALL( SCIPsolFree(&primal->sols[set->limit_maxsol - 1], blkmem, primal) );
1024 }
1025 else
1026 {
1027 primal->nsols = primal->nsols + 1;
1028 assert(primal->nsols <= set->limit_maxsol);
1029 }
1030
1031 /* move all solutions with worse objective value than the new solution */
1032 for( pos = primal->nsols-1; pos > insertpos; --pos )
1033 primal->sols[pos] = primal->sols[pos-1];
1034
1035 /* insert solution at correct position */
1036 assert(0 <= insertpos && insertpos < primal->nsols);
1037 primal->sols[insertpos] = sol;
1038 primal->nsolsfound++;
1039
1040 /* check if solution is better than objective limit */
1041 if( SCIPsetIsFeasLE(set, obj, SCIPprobInternObjval(transprob, origprob, set, SCIPprobGetObjlim(origprob, set))) )
1042 primal->nlimsolsfound++;
1043 }
1044
1045 /* if its the first primal solution, store the relevant statistics */
1046 if( primal->nsolsfound == 1 )
1047 {
1048 SCIP_Real primalsolval;
1049
1052 stat->firstprimalheur = SCIPsolGetHeur(sol);
1053 stat->firstprimaltime = SCIPsolGetTime(sol);
1054 stat->firstprimaldepth = SCIPsolGetDepth(sol);
1055
1056 primalsolval = obj;
1057 stat->firstprimalbound = SCIPprobExternObjval(transprob, origprob, set, primalsolval);
1058
1059 SCIPsetDebugMsg(set, "First Solution stored in problem specific statistics.\n");
1060 SCIPsetDebugMsg(set, "-> %" SCIP_LONGINT_FORMAT " nodes, %d runs, %.2g time, %d depth, %.15g objective\n", stat->nnodesbeforefirst, stat->nrunsbeforefirst,
1062 }
1063
1064 SCIPsetDebugMsg(set, " -> stored at position %d of %d solutions, found %" SCIP_LONGINT_FORMAT " solutions\n",
1065 insertpos, primal->nsols, primal->nsolsfound);
1066
1067 /* update the solution value sums in variables */
1068 if( !SCIPsolIsOriginal(sol) )
1069 {
1070 SCIPsolUpdateVarsum(sol, set, stat, transprob,
1071 (SCIP_Real)(primal->nsols - insertpos)/(SCIP_Real)(2.0*primal->nsols - 1.0));
1072 }
1073
1074 /* change color of node in visualization output */
1075 SCIPvisualFoundSolution(stat->visual, set, stat, SCIPtreeGetCurrentNode(tree), insertpos == 0 ? TRUE : FALSE, sol);
1076
1077 /* check, if the global upper bound has to be updated */
1078 if( obj < primal->cutoffbound && insertpos == 0 )
1079 {
1080 /* issue BESTSOLFOUND event */
1082 SCIP_CALL( SCIPeventChgSol(&event, sol) );
1083 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
1084
1085 /* update the upper bound */
1086 SCIP_CALL( SCIPprimalSetUpperbound(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, tree, reopt, lp, obj) );
1087
1088 primal->nbestsolsfound++;
1089 stat->bestsolnode = stat->nnodes;
1090 }
1091 else
1092 {
1093 /* issue POORSOLFOUND event */
1095 SCIP_CALL( SCIPeventChgSol(&event, sol) );
1096 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
1097 }
1098
1099 /* display node information line */
1100 if( insertpos == 0 && !replace && set->stage >= SCIP_STAGE_SOLVING )
1101 {
1102 SCIP_CALL( SCIPdispPrintLine(set, messagehdlr, stat, NULL, TRUE, TRUE) );
1103 }
1104
1105 /* if an original solution was added during solving, try to transfer it to the transformed space */
1106 if( SCIPsolIsOriginal(sol) && SCIPsetGetStage(set) == SCIP_STAGE_SOLVING && set->misc_transorigsols )
1107 {
1108 SCIP_Bool added;
1109
1110 SCIP_CALL( SCIPprimalTransformSol(primal, sol, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt,
1111 lp, eventqueue, eventfilter, NULL, NULL, 0, &added) );
1112
1113 SCIPsetDebugMsg(set, "original solution %p was successfully transferred to the transformed problem space\n",
1114 (void*)sol);
1115 } /*lint !e438*/
1116
1117 return SCIP_OKAY;
1118}
1119
1120/** adds primal solution to solution storage at given position */
1121static
1123 SCIP_PRIMAL* primal, /**< primal data */
1124 BMS_BLKMEM* blkmem, /**< block memory */
1125 SCIP_SET* set, /**< global SCIP settings */
1126 SCIP_PROB* prob, /**< original problem data */
1127 SCIP_SOL* sol, /**< primal CIP solution */
1128 int insertpos /**< position in solution storage to add solution to */
1129 )
1130{
1131 int pos;
1132
1133 assert(primal != NULL);
1134 assert(set != NULL);
1135 assert(prob != NULL);
1136 assert(sol != NULL);
1137 assert(0 <= insertpos && insertpos < set->limit_maxorigsol);
1138 assert(!set->reopt_enable);
1139
1140 SCIPsetDebugMsg(set, "insert primal solution candidate %p with obj %g at position %d:\n", (void*)sol, SCIPsolGetOrigObj(sol), insertpos);
1141
1142 /* allocate memory for solution storage */
1143 SCIP_CALL( ensureSolsSize(primal, set, set->limit_maxorigsol) );
1144
1145 /* if the solution storage is full, free the last solution(s)
1146 * more than one solution may be freed, if set->limit_maxorigsol was decreased in the meantime
1147 */
1148 for( pos = set->limit_maxorigsol-1; pos < primal->nsols; ++pos )
1149 {
1150 SCIP_CALL( SCIPsolFree(&primal->sols[pos], blkmem, primal) );
1151 }
1152
1153 /* insert solution at correct position */
1154 primal->nsols = MIN(primal->nsols+1, set->limit_maxorigsol);
1155 for( pos = primal->nsols-1; pos > insertpos; --pos )
1156 primal->sols[pos] = primal->sols[pos-1];
1157
1158 assert(0 <= insertpos && insertpos < primal->nsols);
1159 primal->sols[insertpos] = sol;
1160 primal->nsolsfound++;
1161
1162 /* check if solution is better than objective limit */
1164 primal->nlimsolsfound++;
1165
1166 SCIPsetDebugMsg(set, " -> stored at position %d of %d solutions, found %" SCIP_LONGINT_FORMAT " solutions\n",
1167 insertpos, primal->nsols, primal->nsolsfound);
1168
1169 return SCIP_OKAY;
1170}
1171
1172/** adds primal solution to solution storage */
1173static
1175 SCIP_PRIMAL* primal, /**< primal data */
1176 SCIP_SET* set, /**< global SCIP settings */
1177 SCIP_PROB* prob, /**< original problem data */
1178 SCIP_SOL* sol /**< primal CIP solution */
1179 )
1180{ /*lint --e{715}*/
1181 assert(primal != NULL);
1182 assert(set != NULL);
1183 assert(prob != NULL);
1184 assert(sol != NULL);
1185
1186 if( primal->npartialsols >= set->limit_maxorigsol )
1187 {
1188 SCIPerrorMessage("Cannot add partial solution to storage: limit reached.\n");
1189 return SCIP_INVALIDCALL;
1190 }
1191
1192 SCIPsetDebugMsg(set, "insert partial solution candidate %p:\n", (void*)sol);
1193
1194 /* allocate memory for solution storage */
1195 SCIP_CALL( ensurePartialsolsSize(primal, set, primal->npartialsols+1) );
1196
1197 primal->partialsols[primal->npartialsols] = sol;
1198 ++primal->npartialsols;
1199
1200 return SCIP_OKAY;
1201}
1202
1203/** uses binary search to find position in solution storage */
1204static
1206 SCIP_PRIMAL* primal, /**< primal data */
1207 SCIP_SET* set, /**< global SCIP settings */
1208 SCIP_PROB* transprob, /**< tranformed problem data */
1209 SCIP_PROB* origprob, /**< original problem data */
1210 SCIP_SOL* sol /**< primal solution to search position for */
1211 )
1212{
1213 SCIP_SOL** sols;
1214 SCIP_Real obj;
1215 SCIP_Real middleobj;
1216 int left;
1217 int right;
1218 int middle;
1219
1220 assert(primal != NULL);
1221
1222 obj = SCIPsolGetObj(sol, set, transprob, origprob);
1223 sols = primal->sols;
1224
1225 left = -1;
1226 right = primal->nsols;
1227 while( left < right-1 )
1228 {
1229 middle = (left+right)/2;
1230 assert(left < middle && middle < right);
1231 assert(0 <= middle && middle < primal->nsols);
1232
1233 middleobj = SCIPsolGetObj(sols[middle], set, transprob, origprob);
1234
1235 if( obj < middleobj )
1236 right = middle;
1237 else
1238 left = middle;
1239 }
1240 assert(left == right-1);
1241
1242 /* prefer solutions that live in the transformed space */
1243 if( !SCIPsolIsOriginal(sol) )
1244 {
1245 while( right > 0 && SCIPsolIsOriginal(sols[right-1])
1246 && SCIPsetIsEQ(set, SCIPsolGetObj(sols[right-1], set, transprob, origprob), obj) )
1247 --right;
1248 }
1249
1250 return right;
1251}
1252
1253/** uses binary search to find position in solution storage */
1254static
1256 SCIP_PRIMAL* primal, /**< primal data */
1257 SCIP_SOL* sol /**< primal solution to search position for */
1258 )
1259{
1260 SCIP_Real obj;
1261 SCIP_Real middleobj;
1262 int left;
1263 int right;
1264 int middle;
1265
1266 assert(primal != NULL);
1267
1268 obj = SCIPsolGetOrigObj(sol);
1269
1270 left = -1;
1271 right = primal->nsols;
1272 while( left < right-1 )
1273 {
1274 middle = (left+right)/2;
1275 assert(left < middle && middle < right);
1276 assert(0 <= middle && middle < primal->nsols);
1277 middleobj = SCIPsolGetOrigObj(primal->sols[middle]);
1278 if( obj < middleobj )
1279 right = middle;
1280 else
1281 left = middle;
1282 }
1283 assert(left == right-1);
1284
1285 return right;
1286}
1287
1288/** returns whether the given primal solution is already existent in the solution storage */
1289static
1291 SCIP_PRIMAL* primal, /**< primal data */
1292 SCIP_SET* set, /**< global SCIP settings */
1293 SCIP_STAT* stat, /**< problem statistics data */
1294 SCIP_PROB* origprob, /**< original problem */
1295 SCIP_PROB* transprob, /**< transformed problem after presolve */
1296 SCIP_SOL* sol, /**< primal solution to search position for */
1297 int* insertpos, /**< pointer to insertion position returned by primalSearchSolPos(); the
1298 * position might be changed if an existing solution should be replaced */
1299 SCIP_Bool* replace /**< pointer to store whether the solution at insertpos should be replaced */
1300 )
1301{
1302 SCIP_Real obj;
1303 int i;
1304
1305 assert(primal != NULL);
1306 assert(insertpos != NULL);
1307 assert(replace != NULL);
1308 assert(0 <= (*insertpos) && (*insertpos) <= primal->nsols);
1309
1310 obj = SCIPsolGetObj(sol, set, transprob, origprob);
1311
1312 assert(primal->sols != NULL || primal->nsols == 0);
1313 assert(primal->sols != NULL || (*insertpos) == 0);
1314
1315 /* search in the better solutions */
1316 for( i = (*insertpos)-1; i >= 0; --i )
1317 {
1318 SCIP_Real solobj;
1319
1320 solobj = SCIPsolGetObj(primal->sols[i], set, transprob, origprob);
1321
1322 /* due to transferring the objective value of transformed solutions to the original space, small numerical errors might occur
1323 * which can lead to SCIPsetIsLE() failing in case of high absolute numbers
1324 */
1325 assert(SCIPsetIsLE(set, solobj, obj) || (REALABS(obj) > 1e+13 * SCIPsetEpsilon(set) && SCIPsetIsFeasLE(set, solobj, obj)));
1326
1327 if( SCIPsetIsLT(set, solobj, obj) )
1328 break;
1329
1330 if( SCIPsolsAreEqual(sol, primal->sols[i], set, stat, origprob, transprob) )
1331 {
1332 if( set->stage >= SCIP_STAGE_PRESOLVED && SCIPsolIsOriginal(primal->sols[i]) && !SCIPsolIsOriginal(sol) )
1333 {
1334 (*insertpos) = i;
1335 (*replace) = TRUE;
1336 }
1337 return TRUE;
1338 }
1339 }
1340
1341 /* search in the worse solutions */
1342 for( i = (*insertpos); i < primal->nsols; ++i )
1343 {
1344 SCIP_Real solobj;
1345
1346 solobj = SCIPsolGetObj(primal->sols[i], set, transprob, origprob);
1347
1348 /* due to transferring the objective value of transformed solutions to the original space, small numerical errors might occur
1349 * which can lead to SCIPsetIsLE() failing in case of high absolute numbers
1350 */
1351 assert(SCIPsetIsGE(set, solobj, obj) || (REALABS(obj) > 1e+13 * SCIPsetEpsilon(set) && SCIPsetIsFeasGE(set, solobj, obj)));
1352
1353 if( SCIPsetIsGT(set, solobj, obj) )
1354 break;
1355
1356 if( SCIPsolsAreEqual(sol, primal->sols[i], set, stat, origprob, transprob) )
1357 {
1358 if( set->stage >= SCIP_STAGE_PRESOLVED && SCIPsolIsOriginal(primal->sols[i]) && !SCIPsolIsOriginal(sol) )
1359 {
1360 (*insertpos) = i;
1361 (*replace) = TRUE;
1362 }
1363 return TRUE;
1364 }
1365 }
1366
1367 return FALSE;
1368}
1369
1370/** returns whether the given primal solution is already existent in the original solution candidate storage */
1371static
1373 SCIP_PRIMAL* primal, /**< primal data */
1374 SCIP_SET* set, /**< global SCIP settings */
1375 SCIP_STAT* stat, /**< problem statistics data */
1376 SCIP_PROB* prob, /**< original problem */
1377 SCIP_SOL* sol, /**< primal solution to search position for */
1378 int insertpos /**< insertion position returned by primalSearchOrigSolPos() */
1379 )
1380{
1381 SCIP_Real obj;
1382 int i;
1383
1384 assert(primal != NULL);
1385 assert(0 <= insertpos && insertpos <= primal->nsols);
1386
1387 obj = SCIPsolGetOrigObj(sol);
1388
1389 /* search in the better solutions */
1390 for( i = insertpos-1; i >= 0; --i )
1391 {
1392 SCIP_Real solobj;
1393
1394 solobj = SCIPsolGetOrigObj(primal->sols[i]);
1395 assert( SCIPsetIsLE(set, solobj, obj) );
1396
1397 if( SCIPsetIsLT(set, solobj, obj) )
1398 break;
1399
1400 if( SCIPsolsAreEqual(sol, primal->sols[i], set, stat, prob, NULL) )
1401 return TRUE;
1402 }
1403
1404 /* search in the worse solutions */
1405 for( i = insertpos; i < primal->nsols; ++i )
1406 {
1407 SCIP_Real solobj;
1408
1409 solobj = SCIPsolGetOrigObj(primal->sols[i]);
1410 assert( SCIPsetIsGE(set, solobj, obj) );
1411
1412 if( SCIPsetIsGT(set, solobj, obj) )
1413 break;
1414
1415 if( SCIPsolsAreEqual(sol, primal->sols[i], set, stat, prob, NULL) )
1416 return TRUE;
1417 }
1418
1419 return FALSE;
1420}
1421
1422/** check if we are willing to check the solution for feasibility */
1423static
1425 SCIP_PRIMAL* primal, /**< primal data */
1426 SCIP_SET* set, /**< global SCIP settings */
1427 SCIP_STAT* stat, /**< problem statistics data */
1428 SCIP_PROB* origprob, /**< original problem */
1429 SCIP_PROB* transprob, /**< transformed problem after presolve */
1430 SCIP_SOL* sol, /**< primal CIP solution */
1431 int* insertpos, /**< pointer to store the insert position of that solution */
1432 SCIP_Bool* replace /**< pointer to store whether the solution at insertpos should be replaced
1433 * (e.g., because it lives in the original space) */
1434 )
1435{
1436 SCIP_Bool solisacceptable;
1437
1438 /* in exact solving mode, we need to compare the exact objective value with the exact cutoff bound */
1439 if( set->exact_enable )
1440 {
1441 SCIP_RATIONAL* objexact;
1442
1443 SCIP_CALL_ABORT( SCIPrationalCreateBuffer(set->buffer, &objexact) );
1444
1445 /* We may arrive here with a floating-point solution without exact data when, e.g., a floating-point heuristic has
1446 * found a solution and calls SCIPtrySol(). Before checking feasibility of this solution, solOfInterest() is
1447 * called to avoid effort for checking suboptimal solutions. If we conclude TRUE here and the solution is found
1448 * exactly feasible afterwards, then the exact data will be added and the objective value will be recomputed
1449 * exactly. If the floating-point objective value in the else case is wrong, we may accept or reject solutions
1450 * unnecessarily, but this will not lead to incorrect primal bounds or missing an optimal solution, because this
1451 * should come in with SCIPsolIsExact() being true.
1452 */
1453 if( SCIPsolIsExact(sol) )
1454 SCIPsolGetObjExact(sol, set, transprob, origprob, objexact);
1455 else
1456 SCIPrationalSetReal(objexact, SCIPsolGetObj(sol, set, transprob, origprob));
1457
1458 if( !SCIPrationalIsInfinity(objexact) )
1459 solisacceptable = !set->exact_improvingsols || SCIPrationalIsLT(objexact, primal->cutoffboundexact);
1460 else
1461 {
1462 solisacceptable = FALSE;
1463 SCIPwarningMessage(set->scip, "Ignoring primal solution candidate with objective value beyond infinity threshold.\n");
1464 }
1465
1466 SCIPrationalFreeBuffer(set->buffer, &objexact);
1467 }
1468 /* in real solving mode, we need to compare the real objective value with the real cutoff bound */
1469 else
1470 {
1471 SCIP_Real obj = SCIPsolGetObj(sol, set, transprob, origprob);
1472
1473 if( !SCIPsetIsInfinity(set, obj) )
1474 solisacceptable = !set->misc_improvingsols || obj < primal->cutoffbound;
1475 else
1476 {
1477 solisacceptable = FALSE;
1478 SCIPwarningMessage(set->scip, "Ignoring primal solution candidate with objective value beyond infinity threshold.\n");
1479 }
1480 }
1481
1482 /* a solution is acceptable if its objective is finite and either not cut off or non-improving solutions enabled */
1483 if( solisacceptable )
1484 {
1485 /* find insert position for the solution */
1486 (*insertpos) = primalSearchSolPos(primal, set, transprob, origprob, sol);
1487 (*replace) = FALSE;
1488
1489 /* the solution should be added, if the insertpos is smaller than the maximum number of solutions to be stored
1490 * and it does not already exist or it does exist, but the existing solution should be replaced by the new one
1491 */
1492 if( (*insertpos) < set->limit_maxsol &&
1493 (!primalExistsSol(primal, set, stat, origprob, transprob, sol, insertpos, replace) || (*replace)) )
1494 return TRUE;
1495 }
1496
1497 return FALSE;
1498}
1499
1500/** check if we are willing to store the solution candidate for later checking */
1501static
1503 SCIP_PRIMAL* primal, /**< primal data */
1504 SCIP_SET* set, /**< global SCIP settings */
1505 SCIP_STAT* stat, /**< problem statistics data */
1506 SCIP_PROB* origprob, /**< original problem */
1507 SCIP_SOL* sol, /**< primal CIP solution */
1508 int* insertpos /**< pointer to store the insert position of that solution */
1509 )
1510{
1511 assert(SCIPsolIsOriginal(sol));
1512
1513 /* find insert position for the solution */
1514 (*insertpos) = primalSearchOrigSolPos(primal, sol);
1515
1516 if( !set->reopt_enable && (*insertpos) < set->limit_maxorigsol && !primalExistsOrigSol(primal, set, stat, origprob, sol, *insertpos) )
1517 return TRUE;
1518
1519 return FALSE;
1520}
1521
1522/** adds primal solution to solution storage by copying it */
1524 SCIP_PRIMAL* primal, /**< primal data */
1525 BMS_BLKMEM* blkmem, /**< block memory */
1526 SCIP_SET* set, /**< global SCIP settings */
1527 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1528 SCIP_STAT* stat, /**< problem statistics data */
1529 SCIP_PROB* origprob, /**< original problem */
1530 SCIP_PROB* transprob, /**< transformed problem after presolve */
1531 SCIP_TREE* tree, /**< branch and bound tree */
1532 SCIP_REOPT* reopt, /**< reoptimization data structure */
1533 SCIP_LP* lp, /**< current LP data */
1534 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1535 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1536 SCIP_SOL* sol, /**< primal CIP solution */
1537 SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1538 )
1539{
1540 SCIP_Bool replace;
1541 int insertpos;
1542
1543 assert(primal != NULL);
1544 assert(blkmem != NULL);
1545 assert(set != NULL);
1546 assert(messagehdlr != NULL);
1547 assert(stat != NULL);
1548 assert(origprob != NULL);
1549 assert(transprob != NULL);
1550 assert(tree != NULL);
1551 assert(lp != NULL);
1552 assert(eventqueue != NULL);
1553 assert(eventfilter != NULL);
1554 assert(sol != NULL);
1555 assert(stored != NULL);
1556
1557 insertpos = -1;
1558
1559 assert(!SCIPsolIsPartial(sol));
1560
1561 if( solOfInterest(primal, set, stat, origprob, transprob, sol, &insertpos, &replace) )
1562 {
1563 SCIP_SOL* solcopy;
1564#ifdef SCIP_MORE_DEBUG
1565 int i;
1566#endif
1567
1568 assert(insertpos >= 0 && insertpos < set->limit_maxsol);
1569
1570 /* create a copy of the solution */
1571 SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, primal, sol) );
1572
1573 /* insert copied solution into solution storage */
1574 if( SCIPsolIsExact(sol) )
1575 {
1576 SCIP_CALL( primalAddSolExact(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1577 tree, reopt, lp->lpexact, eventqueue, eventfilter, &solcopy, insertpos, replace) );
1578 }
1579 else
1580 {
1581 SCIP_CALL( primalAddSol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1582 tree, reopt, lp, eventqueue, eventfilter, &solcopy, insertpos, replace) );
1583 }
1584#ifdef SCIP_MORE_DEBUG
1585 for( i = 0; i < primal->nsols - 1; ++i )
1586 {
1587 assert(SCIPsetIsLE(set, SCIPsolGetObj(primal->sols[i], set, transprob, origprob), SCIPsolGetObj(primal->sols[i+1], set, transprob, origprob)));
1588 }
1589#endif
1590 *stored = TRUE;
1591 }
1592 else
1593 *stored = FALSE;
1594
1595 return SCIP_OKAY;
1596}
1597
1598/** adds primal solution to solution storage, frees the solution afterwards */
1600 SCIP_PRIMAL* primal, /**< primal data */
1601 BMS_BLKMEM* blkmem, /**< block memory */
1602 SCIP_SET* set, /**< global SCIP settings */
1603 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1604 SCIP_STAT* stat, /**< problem statistics data */
1605 SCIP_PROB* origprob, /**< original problem */
1606 SCIP_PROB* transprob, /**< transformed problem after presolve */
1607 SCIP_TREE* tree, /**< branch and bound tree */
1608 SCIP_REOPT* reopt, /**< reoptimization data structure */
1609 SCIP_LP* lp, /**< current LP data */
1610 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1611 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1612 SCIP_SOL** sol, /**< pointer to primal CIP solution; is cleared in function call */
1613 SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1614 )
1615{
1616 SCIP_Bool replace;
1617 int insertpos;
1618
1619 assert(primal != NULL);
1620 assert(transprob != NULL);
1621 assert(origprob != NULL);
1622 assert(sol != NULL);
1623 assert(*sol != NULL);
1624 assert(stored != NULL);
1625
1626 insertpos = -1;
1627
1628 if( solOfInterest(primal, set, stat, origprob, transprob, *sol, &insertpos, &replace) )
1629 {
1630 assert(insertpos >= 0 && insertpos < set->limit_maxsol);
1631
1632 /* insert solution into solution storage */
1633 SCIP_CALL( primalAddSol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1634 tree, reopt, lp, eventqueue, eventfilter, sol, insertpos, replace) );
1635
1636 /* clear the pointer, such that the user cannot access the solution anymore */
1637 *sol = NULL;
1638
1639 *stored = TRUE;
1640 }
1641 else
1642 {
1643 /* the solution is too bad -> free it immediately */
1644 SCIP_CALL( SCIPsolFree(sol, blkmem, primal) );
1645
1646 *stored = FALSE;
1647 }
1648 assert(*sol == NULL);
1649
1650 return SCIP_OKAY;
1651}
1652
1653/** adds primal solution to solution candidate storage of original problem space */
1655 SCIP_PRIMAL* primal, /**< primal data */
1656 BMS_BLKMEM* blkmem, /**< block memory */
1657 SCIP_SET* set, /**< global SCIP settings */
1658 SCIP_STAT* stat, /**< problem statistics data */
1659 SCIP_PROB* prob, /**< original problem data */
1660 SCIP_SOL* sol, /**< primal CIP solution; is cleared in function call */
1661 SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1662 )
1663{
1664 int insertpos;
1665
1666 assert(primal != NULL);
1667 assert(blkmem != NULL);
1668 assert(set != NULL);
1669 assert(stat != NULL);
1670 assert(sol != NULL);
1671 assert(SCIPsolIsOriginal(sol));
1672 assert(stored != NULL);
1673
1674 insertpos = -1;
1675
1676 if( SCIPsolIsPartial(sol) )
1677 {
1678 SCIP_SOL* solcopy;
1679
1680 /* create a copy of the solution */
1681 SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, primal, sol) );
1682
1683 SCIP_CALL( primalAddOrigPartialSol(primal, set, prob, solcopy) );
1684
1685 *stored = TRUE;
1686 }
1687 else if( origsolOfInterest(primal, set, stat, prob, sol, &insertpos) )
1688 {
1689 SCIP_SOL* solcopy;
1690
1691 assert(insertpos >= 0 && insertpos < set->limit_maxorigsol);
1692 assert(!set->reopt_enable);
1693
1694 /* create a copy of the solution */
1695 SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, primal, sol) );
1696
1697 /* insert solution into solution storage */
1698 SCIP_CALL( primalAddOrigSol(primal, blkmem, set, prob, solcopy, insertpos) );
1699
1700 *stored = TRUE;
1701 }
1702 else
1703 *stored = FALSE;
1704
1705 return SCIP_OKAY;
1706}
1707
1708/** adds primal solution to solution candidate storage of original problem space, frees the solution afterwards */
1710 SCIP_PRIMAL* primal, /**< primal data */
1711 BMS_BLKMEM* blkmem, /**< block memory */
1712 SCIP_SET* set, /**< global SCIP settings */
1713 SCIP_STAT* stat, /**< problem statistics data */
1714 SCIP_PROB* prob, /**< original problem data */
1715 SCIP_SOL** sol, /**< pointer to primal CIP solution; is cleared in function call */
1716 SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1717 )
1718{
1719 int insertpos;
1720
1721 assert(primal != NULL);
1722 assert(sol != NULL);
1723 assert(*sol != NULL);
1724 assert(SCIPsolIsOriginal(*sol));
1725 assert(stored != NULL);
1726
1727 insertpos = -1;
1728
1729 if( SCIPsolIsPartial(*sol) )
1730 {
1731 /* insert solution into solution storage */
1732 SCIP_CALL( primalAddOrigPartialSol(primal, set, prob, *sol) );
1733
1734 /* clear the pointer, such that the user cannot access the solution anymore */
1735 *sol = NULL;
1736
1737 *stored = TRUE;
1738 }
1739 else if( origsolOfInterest(primal, set, stat, prob, *sol, &insertpos) )
1740 {
1741 assert(insertpos >= 0 && insertpos < set->limit_maxorigsol);
1742 assert(!set->reopt_enable);
1743
1744 /* insert solution into solution storage */
1745 SCIP_CALL( primalAddOrigSol(primal, blkmem, set, prob, *sol, insertpos) );
1746
1747 /* clear the pointer, such that the user cannot access the solution anymore */
1748 *sol = NULL;
1749
1750 *stored = TRUE;
1751 }
1752 else
1753 {
1754 /* the solution is too bad -> free it immediately */
1755 SCIP_CALL( SCIPsolFree(sol, blkmem, primal) );
1756
1757 *stored = FALSE;
1758 }
1759 assert(*sol == NULL);
1760
1761 return SCIP_OKAY;
1762}
1763
1764/** links temporary solution of primal data to current solution */
1765static
1767 SCIP_PRIMAL* primal, /**< primal data */
1768 BMS_BLKMEM* blkmem, /**< block memory */
1769 SCIP_SET* set, /**< global SCIP settings */
1770 SCIP_STAT* stat, /**< problem statistics data */
1771 SCIP_PROB* prob, /**< transformed problem data */
1772 SCIP_TREE* tree, /**< branch and bound tree */
1773 SCIP_LP* lp, /**< current LP data */
1774 SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */
1775 )
1776{
1777 assert(primal != NULL);
1778
1779 if( primal->currentsol == NULL )
1780 {
1781 SCIP_CALL( SCIPsolCreateCurrentSol(&primal->currentsol, blkmem, set, stat, prob, primal, tree, lp, heur) );
1782 }
1783 else
1784 {
1785 SCIP_CALL( SCIPsolLinkCurrentSol(primal->currentsol, set, stat, prob, tree, lp) );
1786 SCIPsolSetHeur(primal->currentsol, heur);
1787 }
1788
1789 return SCIP_OKAY;
1790}
1791
1792/** adds current LP/pseudo solution to solution storage */
1794 SCIP_PRIMAL* primal, /**< primal data */
1795 BMS_BLKMEM* blkmem, /**< block memory */
1796 SCIP_SET* set, /**< global SCIP settings */
1797 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1798 SCIP_STAT* stat, /**< problem statistics data */
1799 SCIP_PROB* origprob, /**< original problem */
1800 SCIP_PROB* transprob, /**< transformed problem after presolve */
1801 SCIP_TREE* tree, /**< branch and bound tree */
1802 SCIP_REOPT* reopt, /**< reoptimization data structure */
1803 SCIP_LP* lp, /**< current LP data */
1804 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1805 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1806 SCIP_HEUR* heur, /**< heuristic that found the solution (or NULL if it's from the tree) */
1807 SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1808 )
1809{
1810 assert(primal != NULL);
1811
1812 /* link temporary solution to current solution */
1813 SCIP_CALL( primalLinkCurrentSol(primal, blkmem, set, stat, transprob, tree, lp, heur) );
1814
1815 /* add solution to solution storage */
1816 SCIP_CALL( SCIPprimalAddSol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1817 tree, reopt, lp, eventqueue, eventfilter, primal->currentsol, stored) );
1818
1819 return SCIP_OKAY;
1820}
1821
1822/** checks primal solution; if feasible, adds it to storage by copying it */
1824 SCIP_PRIMAL* primal, /**< primal data */
1825 BMS_BLKMEM* blkmem, /**< block memory */
1826 SCIP_SET* set, /**< global SCIP settings */
1827 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1828 SCIP_STAT* stat, /**< problem statistics data */
1829 SCIP_PROB* origprob, /**< original problem */
1830 SCIP_PROB* transprob, /**< transformed problem after presolve */
1831 SCIP_TREE* tree, /**< branch and bound tree */
1832 SCIP_REOPT* reopt, /**< reoptimization data structure */
1833 SCIP_LP* lp, /**< current LP data */
1834 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1835 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1836 SCIP_SOL* sol, /**< primal CIP solution */
1837 SCIP_Bool printreason, /**< Should all reasons of violations be printed? */
1838 SCIP_Bool completely, /**< Should all violations be checked? */
1839 SCIP_Bool checkbounds, /**< Should the bounds of the variables be checked? */
1840 SCIP_Bool checkintegrality, /**< Has integrality to be checked? */
1841 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
1842 SCIP_Bool* stored /**< stores whether given solution was feasible and good enough to keep */
1843 )
1844{
1845 SCIP_Bool feasible;
1846 SCIP_Bool replace;
1847 int insertpos;
1848
1849 assert(primal != NULL);
1850 assert(set != NULL);
1851 assert(transprob != NULL);
1852 assert(origprob != NULL);
1853 assert(tree != NULL);
1854 assert(sol != NULL);
1855 assert(stored != NULL);
1856
1857 /* if we want to solve exactly, the constraint handlers cannot rely on the LP's feasibility */
1858 checklprows = checklprows || set->exact_enable;
1859
1860 insertpos = -1;
1861
1862 if( solOfInterest(primal, set, stat, origprob, transprob, sol, &insertpos, &replace) )
1863 {
1864 /* check solution for feasibility */
1865 SCIP_CALL( SCIPsolCheck(sol, set, messagehdlr, blkmem, stat, transprob, printreason, completely, checkbounds,
1866 checkintegrality, checklprows, &feasible) );
1867 }
1868 else
1869 feasible = FALSE;
1870
1871 if( feasible )
1872 {
1873 SCIP_SOL* solcopy;
1874
1875 assert(insertpos >= 0 && insertpos < set->limit_maxsol);
1876
1877 /* create a copy of the solution */
1878 SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, primal, sol) );
1879
1880 /* insert copied solution into solution storage */
1881 SCIP_CALL( primalAddSol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1882 tree, reopt, lp, eventqueue, eventfilter, &solcopy, insertpos, replace) );
1883
1884 *stored = TRUE;
1885 }
1886 else
1887 *stored = FALSE;
1888
1889 return SCIP_OKAY;
1890}
1891
1892/** checks primal solution; if feasible, adds it to storage; solution is freed afterwards */
1894 SCIP_PRIMAL* primal, /**< primal data */
1895 BMS_BLKMEM* blkmem, /**< block memory */
1896 SCIP_SET* set, /**< global SCIP settings */
1897 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1898 SCIP_STAT* stat, /**< problem statistics data */
1899 SCIP_PROB* origprob, /**< original problem */
1900 SCIP_PROB* transprob, /**< transformed problem after presolve */
1901 SCIP_TREE* tree, /**< branch and bound tree */
1902 SCIP_REOPT* reopt, /**< reoptimization data structure */
1903 SCIP_LP* lp, /**< current LP data */
1904 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1905 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1906 SCIP_SOL** sol, /**< pointer to primal CIP solution; is cleared in function call */
1907 SCIP_Bool printreason, /**< Should all the reasons of violations be printed? */
1908 SCIP_Bool completely, /**< Should all violations be checked? */
1909 SCIP_Bool checkbounds, /**< Should the bounds of the variables be checked? */
1910 SCIP_Bool checkintegrality, /**< Has integrality to be checked? */
1911 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
1912 SCIP_Bool* stored /**< stores whether solution was feasible and good enough to keep */
1913 )
1914{
1915 SCIP_Bool feasible;
1916 SCIP_Bool replace;
1917 int insertpos;
1918
1919 assert(primal != NULL);
1920 assert(transprob != NULL);
1921 assert(origprob != NULL);
1922 assert(tree != NULL);
1923 assert(sol != NULL);
1924 assert(*sol != NULL);
1925 assert(stored != NULL);
1926
1927 *stored = FALSE;
1928
1929 /* if we want to solve exactly, the constraint handlers cannot rely on the LP's feasibility */
1930 checklprows = checklprows || set->exact_enable;
1931
1932 insertpos = -1;
1933
1934 if( solOfInterest(primal, set, stat, origprob, transprob, *sol, &insertpos, &replace) )
1935 {
1936 /* check solution for feasibility */
1937 SCIP_CALL( SCIPsolCheck(*sol, set, messagehdlr, blkmem, stat, transprob, printreason, completely, checkbounds,
1938 checkintegrality, checklprows, &feasible) );
1939 }
1940 else
1941 feasible = FALSE;
1942
1943 if( feasible )
1944 {
1945 assert(insertpos >= 0 && insertpos < set->limit_maxsol);
1946
1947 /* insert solution into solution storage */
1948 SCIP_CALL( primalAddSol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1949 tree, reopt, lp, eventqueue, eventfilter, sol, insertpos, replace) );
1950
1951 /* clear the pointer, such that the user cannot access the solution anymore */
1952 *sol = NULL;
1953 *stored = TRUE;
1954 }
1955 else
1956 {
1957 /* the solution is too bad or infeasible -> free it immediately */
1958 SCIP_CALL( SCIPsolFree(sol, blkmem, primal) );
1959 *stored = FALSE;
1960 }
1961 assert(*sol == NULL);
1962
1963 return SCIP_OKAY;
1964}
1965
1966/** checks current LP/pseudo solution; if feasible, adds it to storage */
1968 SCIP_PRIMAL* primal, /**< primal data */
1969 BMS_BLKMEM* blkmem, /**< block memory */
1970 SCIP_SET* set, /**< global SCIP settings */
1971 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1972 SCIP_STAT* stat, /**< problem statistics data */
1973 SCIP_PROB* origprob, /**< original problem */
1974 SCIP_PROB* transprob, /**< transformed problem after presolve */
1975 SCIP_TREE* tree, /**< branch and bound tree */
1976 SCIP_REOPT* reopt, /**< reoptimization data structure */
1977 SCIP_LP* lp, /**< current LP data */
1978 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1979 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1980 SCIP_HEUR* heur, /**< heuristic that found the solution (or NULL if it's from the tree) */
1981 SCIP_Bool printreason, /**< Should all reasons of violations be printed? */
1982 SCIP_Bool completely, /**< Should all violations be checked? */
1983 SCIP_Bool checkintegrality, /**< Has integrality to be checked? */
1984 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
1985 SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1986 )
1987{
1988 assert(primal != NULL);
1989
1990 /* link temporary solution to current solution */
1991 SCIP_CALL( primalLinkCurrentSol(primal, blkmem, set, stat, transprob, tree, lp, heur) );
1992
1993 /* add solution to solution storage */
1994 SCIP_CALL( SCIPprimalTrySol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1995 tree, reopt, lp, eventqueue, eventfilter, primal->currentsol,
1996 printreason, completely, FALSE, checkintegrality, checklprows, stored) );
1997
1998 return SCIP_OKAY;
1999}
2000
2001/** inserts solution into the global array of all existing primal solutions */
2003 SCIP_PRIMAL* primal, /**< primal data */
2004 SCIP_SET* set, /**< global SCIP settings */
2005 SCIP_SOL* sol /**< primal CIP solution */
2006 )
2007{
2008 assert(primal != NULL);
2009 assert(sol != NULL);
2010 assert(SCIPsolGetPrimalIndex(sol) == -1);
2011
2012 /* allocate memory for solution storage */
2013 SCIP_CALL( ensureExistingsolsSize(primal, set, primal->nexistingsols+1) );
2014
2015 /* append solution */
2017 primal->existingsols[primal->nexistingsols] = sol;
2018 primal->nexistingsols++;
2019
2020 return SCIP_OKAY;
2021}
2022
2023/** removes solution from the global array of all existing primal solutions */
2025 SCIP_PRIMAL* primal, /**< primal data */
2026 SCIP_SOL* sol /**< primal CIP solution */
2027 )
2028{
2029 int idx;
2030
2031 assert(primal != NULL);
2032 assert(sol != NULL);
2033
2034#ifndef NDEBUG
2035 for( idx = 0; idx < primal->nexistingsols; ++idx )
2036 {
2037 assert(idx == SCIPsolGetPrimalIndex(primal->existingsols[idx]));
2038 }
2039#endif
2040
2041 /* remove solution */
2042 idx = SCIPsolGetPrimalIndex(sol);
2043 assert(0 <= idx && idx < primal->nexistingsols);
2044 assert(sol == primal->existingsols[idx]);
2045 if( idx < primal->nexistingsols-1 )
2046 {
2047 primal->existingsols[idx] = primal->existingsols[primal->nexistingsols-1];
2048 SCIPsolSetPrimalIndex(primal->existingsols[idx], idx);
2049 }
2050 primal->nexistingsols--;
2051}
2052
2053/** updates all existing primal solutions after a change in a variable's objective value */
2055 SCIP_PRIMAL* primal, /**< primal data */
2056 SCIP_VAR* var, /**< problem variable */
2057 SCIP_Real oldobj, /**< old objective value */
2058 SCIP_Real newobj /**< new objective value */
2059 )
2060{
2061 int i;
2062
2063 assert(primal != NULL);
2064
2065 for( i = 0; i < primal->nexistingsols; ++i )
2066 {
2067 if( !SCIPsolIsOriginal(primal->existingsols[i]) )
2068 SCIPsolUpdateVarObj(primal->existingsols[i], var, oldobj, newobj);
2069 }
2070}
2071
2072/** retransforms all existing solutions to original problem space
2073 *
2074 * @note as a side effect, the objective value of the solutions can change (numerical errors)
2075 * so we update the objective cutoff value and upper bound accordingly
2076 */
2078 SCIP_PRIMAL* primal, /**< primal data */
2079 BMS_BLKMEM* blkmem, /**< block memory */
2080 SCIP_SET* set, /**< global SCIP settings */
2081 SCIP_STAT* stat, /**< problem statistics data */
2082 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2083 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
2084 SCIP_PROB* origprob, /**< original problem */
2085 SCIP_PROB* transprob, /**< transformed problem */
2086 SCIP_TREE* tree, /**< branch and bound tree */
2087 SCIP_REOPT* reopt, /**< reoptimization data structure */
2088 SCIP_LP* lp /**< current LP data */
2089 )
2090{
2091 SCIP_Bool hasinfval;
2092 int i;
2093
2094 assert(primal != NULL);
2095
2096 for( i = 0; i < primal->nsols; ++i )
2097 {
2098 if( SCIPsolGetOrigin(primal->sols[i]) == SCIP_SOLORIGIN_ZERO )
2099 {
2100 SCIP_CALL( SCIPsolRetransform(primal->sols[i], set, stat, origprob, transprob, &hasinfval) );
2101 }
2102 }
2103
2104 sortPrimalSols(primal, set, origprob, transprob);
2105
2106 /* check if the global upper bound has to be updated
2107 * @todo we do not inform anybody about this change; if this leads to some
2108 * problem, a possible solution is to issue a BESTSOLFOUND event
2109 */
2110 if( primal->nsols > 0 )
2111 {
2112 SCIP_Real obj;
2113
2114 obj = SCIPsolGetObj(primal->sols[0], set, transprob, origprob);
2115 if( obj < primal->cutoffbound )
2116 {
2117 /* update the upper bound */
2118 SCIP_CALL( SCIPprimalSetUpperbound(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, tree, reopt, lp, obj) );
2119 }
2120 }
2121
2122 return SCIP_OKAY;
2123}
2124
2125/** tries to transform original solution to the transformed problem space */
2127 SCIP_PRIMAL* primal, /**< primal data */
2128 SCIP_SOL* sol, /**< primal solution */
2129 BMS_BLKMEM* blkmem, /**< block memory */
2130 SCIP_SET* set, /**< global SCIP settings */
2131 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2132 SCIP_STAT* stat, /**< problem statistics data */
2133 SCIP_PROB* origprob, /**< original problem */
2134 SCIP_PROB* transprob, /**< transformed problem after presolve */
2135 SCIP_TREE* tree, /**< branch and bound tree */
2136 SCIP_REOPT* reopt, /**< reoptimization data structure */
2137 SCIP_LP* lp, /**< current LP data */
2138 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2139 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
2140 SCIP_Real* solvals, /**< array for internal use to store solution values, or NULL;
2141 * if the method is called multiple times in a row, an array with size >=
2142 * number of active variables should be given for performance reasons */
2143 SCIP_Bool* solvalset, /**< array for internal use to store which solution values were set, or NULL;
2144 * if the method is called multiple times in a row, an array with size >=
2145 * number of active variables should be given for performance reasons */
2146 int solvalssize, /**< size of solvals and solvalset arrays, should be >= number of active
2147 * variables */
2148 SCIP_Bool* added /**< pointer to store whether the solution was added */
2149 )
2150{
2151 SCIP_VAR** origvars;
2152 SCIP_VAR** transvars;
2153 SCIP_VAR* var;
2154 SCIP_Real* localsolvals;
2155 SCIP_Bool* localsolvalset;
2156 SCIP_Real solval;
2157 SCIP_Real scalar;
2158 SCIP_Real constant;
2159 SCIP_Bool localarrays;
2160 SCIP_Bool feasible;
2161 int norigvars;
2162 int ntransvars;
2163 int nvarsset;
2164 int v;
2165
2166 assert(origprob != NULL);
2167 assert(transprob != NULL);
2168 assert(SCIPsolIsOriginal(sol));
2169 assert(solvalssize == 0 || solvals != NULL);
2170 assert(solvalssize == 0 || solvalset != NULL);
2171
2172 origvars = SCIPprobGetVars(origprob);
2173 norigvars = SCIPprobGetNVars(origprob);
2174 transvars = SCIPprobGetVars(transprob);
2175 ntransvars = SCIPprobGetNVars(transprob);
2176 assert(solvalssize == 0 || solvalssize >= ntransvars);
2177
2178 SCIPsetDebugMsg(set, "try to transfer original solution %p with objective %g into the transformed problem space\n",
2179 (void*)sol, SCIPsolGetOrigObj(sol));
2180
2181 /* if no solvals and solvalset arrays are given, allocate local ones, otherwise use the given ones */
2182 localarrays = (solvalssize == 0);
2183 if( localarrays )
2184 {
2185 SCIP_CALL( SCIPsetAllocBufferArray(set, &localsolvals, ntransvars) );
2186 SCIP_CALL( SCIPsetAllocBufferArray(set, &localsolvalset, ntransvars) );
2187 }
2188 else
2189 {
2190 localsolvals = solvals;
2191 localsolvalset = solvalset;
2192 }
2193
2194 BMSclearMemoryArray(localsolvalset, ntransvars);
2195 feasible = TRUE;
2196 (*added) = FALSE;
2197 nvarsset = 0;
2198
2199 /* for each original variable, get the corresponding active, fixed or multi-aggregated variable;
2200 * if it resolves to an active variable, we set its solution value or check whether an already stored solution value
2201 * is consistent; if it resolves to a fixed variable, we check that the fixing matches the original solution value;
2202 * multi-aggregated variables are skipped, because their value is defined by setting solution values for the active
2203 * variables, anyway
2204 */
2205 for( v = 0; v < norigvars && feasible; ++v )
2206 {
2207 var = origvars[v];
2208
2209 solval = SCIPsolGetVal(sol, set, stat, var);
2210
2211 /* get corresponding active, fixed, or multi-aggregated variable */
2212 scalar = 1.0;
2213 constant = 0.0;
2214 SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &constant) );
2217
2218 /* check whether the fixing corresponds to the solution value of the original variable */
2219 if( scalar == 0.0 )
2220 {
2221 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED ||
2222 (SCIPsetIsInfinity(set, constant) || SCIPsetIsInfinity(set, -constant)));
2223
2224 if( !SCIPsetIsEQ(set, solval, constant) )
2225 {
2226 SCIPsetDebugMsg(set, "original variable <%s> (solval=%g) resolves to fixed variable <%s> (original solval=%g)\n",
2227 SCIPvarGetName(origvars[v]), solval, SCIPvarGetName(var), constant);
2228 feasible = FALSE;
2229 }
2230 }
2231 else if( SCIPvarIsActive(var) )
2232 {
2233 /* if we already assigned a solution value to the transformed variable, check that it corresponds to the
2234 * value obtained from the currently regarded original variable
2235 */
2236 if( localsolvalset[SCIPvarGetProbindex(var)] )
2237 {
2238 if( !SCIPsetIsEQ(set, solval, scalar * localsolvals[SCIPvarGetProbindex(var)] + constant) )
2239 {
2240 SCIPsetDebugMsg(set, "original variable <%s> (solval=%g) resolves to active variable <%s> with assigned solval %g (original solval=%g)\n",
2241 SCIPvarGetName(origvars[v]), solval, SCIPvarGetName(var), localsolvals[SCIPvarGetProbindex(var)],
2242 scalar * localsolvals[SCIPvarGetProbindex(var)] + constant);
2243 feasible = FALSE;
2244 }
2245 }
2246 /* assign solution value to the transformed variable */
2247 else
2248 {
2249 assert(scalar != 0.0);
2250
2251 localsolvals[SCIPvarGetProbindex(var)] = (solval - constant) / scalar;
2252 localsolvalset[SCIPvarGetProbindex(var)] = TRUE;
2253 ++nvarsset;
2254 }
2255 }
2256#ifndef NDEBUG
2257 /* we do not have to handle multi-aggregated variables here, since by assigning values to all active variabes,
2258 * we implicitly assign values to the multi-aggregated variables, too
2259 */
2260 else
2262#endif
2263 }
2264
2265 /* if the solution values of fixed and active variables lead to no contradiction, construct solution and try it */
2266 if( feasible )
2267 {
2268 SCIP_SOL* transsol;
2269
2270 SCIP_CALL( SCIPsolCreate(&transsol, blkmem, set, stat, primal, tree, SCIPsolGetHeur(sol)) );
2271
2272 /* set solution values for variables to which we assigned a value */
2273 for( v = 0; v < ntransvars; ++v )
2274 {
2275 if( localsolvalset[v] )
2276 {
2277 SCIP_CALL( SCIPsolSetVal(transsol, set, stat, tree, transvars[v], localsolvals[v]) );
2278 }
2279 }
2280
2281 SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
2282 tree, reopt, lp, eventqueue, eventfilter, &transsol, FALSE, FALSE, TRUE, TRUE, TRUE, added) );
2283
2284 SCIPsetDebugMsg(set, "solution transferred, %d/%d active variables set (stored=%u)\n", nvarsset, ntransvars, *added);
2285 }
2286 else
2287 (*added) = FALSE;
2288
2289 /* free local arrays, if needed */
2290 if( localarrays )
2291 {
2292 SCIPsetFreeBufferArray(set, &localsolvalset);
2293 SCIPsetFreeBufferArray(set, &localsolvals);
2294 }
2295
2296 return SCIP_OKAY;
2297}
2298
2299
2300/** is the updating of violations enabled for this problem? */
2302 SCIP_PRIMAL* primal /**< problem data */
2303 )
2304{
2305 assert(primal != NULL);
2306
2307 return primal->updateviolations;
2308}
2309
2310/** set whether the updating of violations is turned on */
2312 SCIP_PRIMAL* primal, /**< problem data */
2313 SCIP_Bool updateviolations /**< marks whether the updating of violations is turned on */
2314 )
2315{
2316 assert(primal != NULL);
2317
2318 primal->updateviolations = updateviolations;
2319}
2320
2321/** adds exact primal solution to solution storage at given position */
2322static
2324 SCIP_PRIMAL* primal, /**< primal data */
2325 BMS_BLKMEM* blkmem, /**< block memory */
2326 SCIP_SET* set, /**< global SCIP settings */
2327 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2328 SCIP_STAT* stat, /**< problem statistics data */
2329 SCIP_PROB* origprob, /**< original problem */
2330 SCIP_PROB* transprob, /**< transformed problem after presolve */
2331 SCIP_TREE* tree, /**< branch and bound tree */
2332 SCIP_REOPT* reopt, /**< reoptimization data structure */
2333 SCIP_LPEXACT* lpexact, /**< current LP data */
2334 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2335 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
2336 SCIP_SOL** solptr, /**< pointer to primal CIP solution */
2337 int insertpos, /**< position in solution storage to add solution to */
2338 SCIP_Bool replace /**< should the solution at insertpos be replaced by the new solution? */
2339 )
2340{
2341 SCIP_Bool stored;
2342 SCIP_RATIONAL* obj;
2343 SCIP_SOL* sol;
2344
2345 assert(primal != NULL);
2346 assert(set != NULL);
2347 assert(solptr != NULL);
2348 assert(stat != NULL);
2349 assert(transprob != NULL);
2350 assert(origprob != NULL);
2351 assert(0 <= insertpos && insertpos < set->limit_maxsol);
2352 assert(tree == NULL || !SCIPtreeInRepropagation(tree));
2353
2354 sol = *solptr;
2355 assert(sol != NULL);
2356
2357 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &obj) );
2358
2359 SCIPsolGetObjExact(sol, set, transprob, origprob, obj);
2360
2361 SCIPsetDebugMsg(set, "insert exact primal solution %p with obj %g at position %d (replace=%u):\n",
2362 (void*)sol, SCIPrationalGetReal(obj), insertpos, replace);
2363
2364 SCIPdebug( SCIP_CALL( SCIPsolPrintExact(sol, set, messagehdlr, stat, transprob, NULL, NULL, FALSE, FALSE) ) );
2365
2366 /* completely fill the solution's own value array to unlink it from the LP or pseudo solution */
2367 SCIP_CALL( SCIPsolUnlinkExact(sol, set, transprob) );
2368
2369 SCIP_CALL( SCIPsolOverwriteFPSolWithExact(sol, set, stat, origprob, transprob, tree) );
2370
2371 /* note: we copy the solution so to not destroy the double-link between sol and fpsol */
2372 SCIP_CALL( SCIPprimalAddSolFree(primal, blkmem, set, messagehdlr, stat,
2373 origprob, transprob, tree, reopt,
2374 lpexact->fplp, eventqueue, eventfilter, &sol, &stored) );
2375
2376 SCIPrationalFreeBuffer(set->buffer, &obj);
2377
2378 return SCIP_OKAY;
2379}
2380
2381/** adds exact primal solution to solution storage, frees the solution afterwards */
2383 SCIP_PRIMAL* primal, /**< primal data */
2384 BMS_BLKMEM* blkmem, /**< block memory */
2385 SCIP_SET* set, /**< global SCIP settings */
2386 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2387 SCIP_STAT* stat, /**< problem statistics data */
2388 SCIP_PROB* origprob, /**< original problem */
2389 SCIP_PROB* transprob, /**< transformed problem after presolve */
2390 SCIP_TREE* tree, /**< branch and bound tree */
2391 SCIP_REOPT* reopt, /**< reoptimization data structure */
2392 SCIP_LPEXACT* lpexact, /**< current LP data */
2393 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2394 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
2395 SCIP_SOL** sol, /**< pointer to primal CIP solution; is cleared in function call */
2396 SCIP_Bool printreason, /**< Should all the reasons of violations be printed? */
2397 SCIP_Bool completely, /**< Should all violations be checked? */
2398 SCIP_Bool checkbounds, /**< Should the bounds of the variables be checked? */
2399 SCIP_Bool checkintegrality, /**< Has integrality to be checked? */
2400 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
2401 SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
2402 )
2403{
2404 SCIP_Bool replace = FALSE;
2405 SCIP_Bool feasible;
2406 int insertpos;
2407
2408 assert(primal != NULL);
2409 assert(transprob != NULL);
2410 assert(origprob != NULL);
2411 assert(sol != NULL);
2412 assert(*sol != NULL);
2413 assert(stored != NULL);
2414
2415 insertpos = -1;
2416
2417 /* insert solution into solution storage */
2418
2419 if( solOfInterest(primal, set, stat, origprob, transprob, *sol, &insertpos, &replace) )
2420 {
2421 /* check solution for feasibility */
2422 SCIP_CALL( SCIPsolCheck(*sol, set, messagehdlr, blkmem, stat, transprob, printreason, completely, checkbounds,
2423 checkintegrality, checklprows, &feasible) );
2424 }
2425 else
2426 feasible = FALSE;
2427
2428 if( feasible )
2429 {
2430 SCIP_CALL( primalAddSolExact(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
2431 tree, reopt, lpexact, eventqueue, eventfilter, sol, insertpos, replace) );
2432
2433 /* clear the pointer, such that the user cannot access the solution anymore */
2434 *sol = NULL;
2435 *stored = TRUE;
2436 }
2437 else
2438 {
2439 SCIP_CALL( SCIPsolFree(sol, blkmem, primal) );
2440 *stored = FALSE;
2441 }
2442
2443 assert(*sol == NULL);
2444
2445 return SCIP_OKAY;
2446}
2447
2448/** adds exact primal solution to solution storage by copying it and frees the solution afterwards */
2450 SCIP_PRIMAL* primal, /**< primal data */
2451 BMS_BLKMEM* blkmem, /**< block memory */
2452 SCIP_SET* set, /**< global SCIP settings */
2453 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2454 SCIP_STAT* stat, /**< problem statistics data */
2455 SCIP_PROB* origprob, /**< original problem */
2456 SCIP_PROB* transprob, /**< transformed problem after presolve */
2457 SCIP_TREE* tree, /**< branch and bound tree */
2458 SCIP_REOPT* reopt, /**< reoptimization data structure */
2459 SCIP_LPEXACT* lpexact, /**< current exact LP data */
2460 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2461 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
2462 SCIP_SOL** sol, /**< primal CIP solution */
2463 SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
2464 )
2465{
2466 SCIP_Bool replace;
2467 int insertpos;
2468
2469 assert(primal != NULL);
2470 assert(blkmem != NULL);
2471 assert(set != NULL);
2472 assert(messagehdlr != NULL);
2473 assert(stat != NULL);
2474 assert(origprob != NULL);
2475 assert(transprob != NULL);
2476 assert(tree != NULL);
2477 assert(lpexact != NULL);
2478 assert(eventqueue != NULL);
2479 assert(eventfilter != NULL);
2480 assert(*sol != NULL);
2481 assert(stored != NULL);
2482
2483 insertpos = -1;
2484
2485 assert(!SCIPsolIsPartial(*sol));
2486
2487 if( solOfInterest(primal, set, stat, origprob, transprob, *sol, &insertpos, &replace) )
2488 {
2489 assert(insertpos >= 0 && insertpos < set->limit_maxsol);
2490
2491 /* insert copied solution into solution storage */
2492 SCIP_CALL( primalAddSolExact(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
2493 tree, reopt, lpexact, eventqueue, eventfilter, sol, insertpos, replace) );
2494 *stored = TRUE;
2495 *sol = NULL;
2496 }
2497 else
2498 {
2499 /* the solution is too bad -> free it immediately */
2500 SCIP_CALL( SCIPsolFree(sol, blkmem, primal) );
2501
2502 *stored = FALSE;
2503 }
2504 assert(*sol == NULL);
2505
2506 return SCIP_OKAY;
2507}
#define SCIPdebugSolIsEnabled(scip)
Definition: debug.h:316
common defines and data types used in all packages of SCIP
#define NULL
Definition: def.h:248
#define SCIP_INVALID
Definition: def.h:178
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:224
#define SCIP_ALLOC(x)
Definition: def.h:366
#define SCIP_Real
Definition: def.h:156
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define SCIP_CALL_ABORT(x)
Definition: def.h:334
#define SCIP_LONGINT_FORMAT
Definition: def.h:148
#define REALABS(x)
Definition: def.h:182
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_RETCODE SCIPdispPrintLine(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, FILE *file, SCIP_Bool forcedisplay, SCIP_Bool endline)
Definition: disp.c:415
internal methods for displaying runtime statistics
SCIP_RETCODE SCIPeventChgSol(SCIP_EVENT *event, SCIP_SOL *sol)
Definition: event.c:1584
SCIP_RETCODE SCIPeventProcess(SCIP_EVENT *event, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter)
Definition: event.c:1804
SCIP_RETCODE SCIPeventChgType(SCIP_EVENT *event, SCIP_EVENTTYPE eventtype)
Definition: event.c:1204
internal methods for managing events
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
void SCIPrationalMin(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1342
void SCIPrationalSetInfinity(SCIP_RATIONAL *res)
Definition: rational.cpp:618
SCIP_Real SCIPrationalGetReal(SCIP_RATIONAL *rational)
Definition: rational.cpp:2085
void SCIPrationalFreeBlock(BMS_BLKMEM *mem, SCIP_RATIONAL **rational)
Definition: rational.cpp:461
#define SCIPrationalDebugMessage
Definition: rational.h:641
void SCIPrationalRoundInteger(SCIP_RATIONAL *res, SCIP_RATIONAL *src, SCIP_ROUNDMODE_RAT roundmode)
Definition: rational.cpp:2158
SCIP_Bool SCIPrationalIsLT(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
Definition: rational.cpp:1503
void SCIPrationalSetReal(SCIP_RATIONAL *res, SCIP_Real real)
Definition: rational.cpp:603
SCIP_Bool SCIPrationalIsGT(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
Definition: rational.cpp:1474
void SCIPrationalFreeBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:473
SCIP_Bool SCIPrationalIsLEReal(SCIP_RATIONAL *rat, SCIP_Real real)
Definition: rational.cpp:1615
SCIP_RETCODE SCIPrationalCreateBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:123
void SCIPrationalSetRational(SCIP_RATIONAL *res, SCIP_RATIONAL *src)
Definition: rational.cpp:569
void SCIPrationalDiffReal(SCIP_RATIONAL *res, SCIP_RATIONAL *rat, SCIP_Real real)
Definition: rational.cpp:1009
SCIP_Bool SCIPrationalIsInfinity(SCIP_RATIONAL *rational)
Definition: rational.cpp:1660
SCIP_Real SCIPrationalRoundReal(SCIP_RATIONAL *rational, SCIP_ROUNDMODE_RAT roundmode)
Definition: rational.cpp:2110
void SCIPrationalAddReal(SCIP_RATIONAL *res, SCIP_RATIONAL *rat, SCIP_Real real)
Definition: rational.cpp:961
SCIP_SOLORIGIN SCIPsolGetOrigin(SCIP_SOL *sol)
Definition: sol.c:4130
SCIP_Real SCIPsolGetOrigObj(SCIP_SOL *sol)
Definition: sol.c:4170
void SCIPsolOrigAddObjvalExact(SCIP_SOL *sol, SCIP_RATIONAL *addval)
Definition: sol.c:4205
SCIP_Real SCIPsolGetTime(SCIP_SOL *sol)
Definition: sol.c:4219
SCIP_Longint SCIPsolGetNodenum(SCIP_SOL *sol)
Definition: sol.c:4239
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition: sol.c:4259
SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
Definition: sol.c:4140
int SCIPsolGetDepth(SCIP_SOL *sol)
Definition: sol.c:4249
SCIP_Bool SCIPsolIsPartial(SCIP_SOL *sol)
Definition: sol.c:4160
int SCIPsolGetRunnum(SCIP_SOL *sol)
Definition: sol.c:4229
void SCIPsolSetHeur(SCIP_SOL *sol, SCIP_HEUR *heur)
Definition: sol.c:4304
SCIP_Bool SCIPsolIsExact(SCIP_SOL *sol)
Definition: sol.c:4150
SCIP_Real SCIPgetDualbound(SCIP *scip)
SCIP_Real SCIPgetLowerbound(SCIP *scip)
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:23642
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:23386
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:23662
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_RETCODE SCIPlpSetCutoffbound(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_Real cutoffbound)
Definition: lp.c:10451
internal methods for LP management
internal methods for exact LP management
#define BMSfreeMemory(ptr)
Definition: memory.h:145
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:127
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:148
#define BMSallocMemory(ptr)
Definition: memory.h:118
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:427
SCIP_RETCODE SCIPprimalAddCurrentSol(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_HEUR *heur, SCIP_Bool *stored)
Definition: primal.c:1793
void SCIPprimalAddOrigObjoffsetExact(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_RATIONAL *addval)
Definition: primal.c:752
static SCIP_RETCODE primalSetUpperbound(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_Real upperbound)
Definition: primal.c:402
SCIP_RETCODE SCIPprimalUpdateObjoffsetExact(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition: primal.c:646
void SCIPprimalSetUpdateViolations(SCIP_PRIMAL *primal, SCIP_Bool updateviolations)
Definition: primal.c:2311
SCIP_RETCODE SCIPprimalUpdateRay(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *primalray, BMS_BLKMEM *blkmem)
Definition: primal.c:810
static SCIP_RETCODE primalSetCutoffboundExact(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_RATIONAL *cutoffbound)
Definition: primal.c:314
void SCIPprimalSolFreed(SCIP_PRIMAL *primal, SCIP_SOL *sol)
Definition: primal.c:2024
static SCIP_RETCODE primalAddSol(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_SOL **solptr, int insertpos, SCIP_Bool replace)
Definition: primal.c:859
static SCIP_Bool origsolOfInterest(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_SOL *sol, int *insertpos)
Definition: primal.c:1502
SCIP_RETCODE SCIPprimalTrySolFreeExact(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LPEXACT *lpexact, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: primal.c:2382
static int primalSearchSolPos(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_SOL *sol)
Definition: primal.c:1205
SCIP_RETCODE SCIPprimalAddOrigSolFree(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_SOL **sol, SCIP_Bool *stored)
Definition: primal.c:1709
SCIP_RETCODE SCIPprimalTryCurrentSol(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_HEUR *heur, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: primal.c:1967
static SCIP_RETCODE ensureExistingsolsSize(SCIP_PRIMAL *primal, SCIP_SET *set, int num)
Definition: primal.c:111
void SCIPprimalAddOrigObjoffset(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_Real addval)
Definition: primal.c:719
SCIP_RETCODE SCIPprimalFree(SCIP_PRIMAL **primal, BMS_BLKMEM *blkmem)
Definition: primal.c:165
static SCIP_Bool primalExistsOrigSol(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_SOL *sol, int insertpos)
Definition: primal.c:1372
static SCIP_RETCODE primalAddOrigSol(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_SOL *sol, int insertpos)
Definition: primal.c:1122
SCIP_SOL * SCIPprimalGetRay(SCIP_PRIMAL *primal)
Definition: primal.c:800
SCIP_RETCODE SCIPprimalTrySolFree(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: primal.c:1893
SCIP_Bool SCIPprimalUpdateViolations(SCIP_PRIMAL *primal)
Definition: primal.c:2301
SCIP_Bool SCIPprimalUpperboundIsSol(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_PROB *transprob, SCIP_PROB *origprob)
Definition: primal.c:787
SCIP_RETCODE SCIPprimalSetUpperbound(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_Real upperbound)
Definition: primal.c:518
static SCIP_RETCODE ensureSolsSize(SCIP_PRIMAL *primal, SCIP_SET *set, int num)
Definition: primal.c:63
static void sortPrimalSols(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_PROB *origprob, SCIP_PROB *transprob)
Definition: primal.c:241
SCIP_RETCODE SCIPprimalAddOrigSol(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_SOL *sol, SCIP_Bool *stored)
Definition: primal.c:1654
SCIP_RETCODE SCIPprimalSetCutoffbound(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_Real cutoffbound, SCIP_Bool useforobjlimit)
Definition: primal.c:348
void SCIPprimalUpdateVarObj(SCIP_PRIMAL *primal, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: primal.c:2054
SCIP_RETCODE SCIPprimalCreate(SCIP_PRIMAL **primal)
Definition: primal.c:133
static SCIP_RETCODE primalLinkCurrentSol(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_LP *lp, SCIP_HEUR *heur)
Definition: primal.c:1766
SCIP_RETCODE SCIPprimalTrySol(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: primal.c:1823
SCIP_RETCODE SCIPprimalRetransformSolutions(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition: primal.c:2077
SCIP_RETCODE SCIPprimalTransformSol(SCIP_PRIMAL *primal, SCIP_SOL *sol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_Real *solvals, SCIP_Bool *solvalset, int solvalssize, SCIP_Bool *added)
Definition: primal.c:2126
SCIP_RETCODE SCIPprimalAddSolFree(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_SOL **sol, SCIP_Bool *stored)
Definition: primal.c:1599
SCIP_RETCODE SCIPprimalUpdateObjoffset(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition: primal.c:590
SCIP_RETCODE SCIPprimalAddSol(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_SOL *sol, SCIP_Bool *stored)
Definition: primal.c:1523
static int primalSearchOrigSolPos(SCIP_PRIMAL *primal, SCIP_SOL *sol)
Definition: primal.c:1255
SCIP_RETCODE SCIPprimalUpdateObjlimit(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition: primal.c:550
static SCIP_RETCODE primalAddSolExact(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LPEXACT *lpexact, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_SOL **solptr, int insertpos, SCIP_Bool replace)
Definition: primal.c:2323
static SCIP_Bool solOfInterest(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_SOL *sol, int *insertpos, SCIP_Bool *replace)
Definition: primal.c:1424
SCIP_RETCODE SCIPprimalSolCreated(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_SOL *sol)
Definition: primal.c:2002
SCIP_RETCODE SCIPprimalAddSolFreeExact(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LPEXACT *lpexact, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_SOL **sol, SCIP_Bool *stored)
Definition: primal.c:2449
SCIP_RETCODE SCIPprimalClear(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem)
Definition: primal.c:190
static SCIP_RETCODE primalSetUpperboundExact(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_RATIONAL *upperbound)
Definition: primal.c:458
static SCIP_RETCODE primalSetCutoffbound(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_Real cutoffbound)
Definition: primal.c:268
static SCIP_Bool primalExistsSol(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_SOL *sol, int *insertpos, SCIP_Bool *replace)
Definition: primal.c:1290
static SCIP_RETCODE ensurePartialsolsSize(SCIP_PRIMAL *primal, SCIP_SET *set, int num)
Definition: primal.c:86
static SCIP_RETCODE primalAddOrigPartialSol(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_PROB *prob, SCIP_SOL *sol)
Definition: primal.c:1174
internal methods for collecting primal CIP solutions and primal informations
void SCIPprobInternObjvalExact(SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_SET *set, SCIP_RATIONAL *objval, SCIP_RATIONAL *objvalint)
Definition: prob.c:2599
SCIP_Real SCIPprobGetObjlim(SCIP_PROB *prob, SCIP_SET *set)
Definition: prob.c:2837
SCIP_OBJSENSE SCIPprobGetObjsense(SCIP_PROB *prob)
Definition: prob.c:2985
void SCIPprobSetObjlim(SCIP_PROB *prob, SCIP_Real objlim)
Definition: prob.c:1713
SCIP_Bool SCIPprobIsObjIntegral(SCIP_PROB *prob)
Definition: prob.c:2813
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2868
SCIP_Real SCIPprobExternObjval(SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_SET *set, SCIP_Real objval)
Definition: prob.c:2520
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2913
SCIP_Real SCIPprobInternObjval(SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_SET *set, SCIP_Real objval)
Definition: prob.c:2573
internal methods for storing and manipulating the main problem
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebug(x)
Definition: pub_message.h:93
public methods for problem variables
data structures and methods for collecting reoptimization information
public methods for message handling
public methods for querying solving statistics
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6617
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:7136
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:7017
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6993
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6577
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:6402
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6537
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:3197
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:6380
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6557
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6515
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6597
SCIP_Real SCIPsetCutoffbounddelta(SCIP_SET *set)
Definition: set.c:6480
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:7041
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:6080
internal methods for global SCIP settings
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1782
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1775
#define SCIPsetDebugMsg
Definition: set.h:1811
void SCIPsolUpdateVarObj(SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: sol.c:2293
void SCIPsolSetPrimalIndex(SCIP_SOL *sol, int primalindex)
Definition: sol.c:4279
int SCIPsolGetPrimalIndex(SCIP_SOL *sol)
Definition: sol.c:4269
SCIP_RETCODE SCIPsolMakeExact(SCIP_SOL *sol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob)
Definition: sol.c:2870
SCIP_RETCODE SCIPsolLinkCurrentSol(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_LP *lp)
Definition: sol.c:1368
SCIP_RETCODE SCIPsolCheck(SCIP_SOL *sol, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *feasible)
Definition: sol.c:2669
SCIP_RETCODE SCIPsolFree(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_PRIMAL *primal)
Definition: sol.c:1133
SCIP_RETCODE SCIPsolOverwriteFPSolWithExact(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree)
Definition: sol.c:4037
SCIP_RETCODE SCIPsolPrintExact(SCIP_SOL *sol, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_PROB *transprob, FILE *file, SCIP_Bool mipstart, SCIP_Bool printzeros)
Definition: sol.c:3577
SCIP_RETCODE SCIPsolRetransform(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_Bool *hasinfval)
Definition: sol.c:2970
SCIP_RETCODE SCIPsolCreateCurrentSol(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_LP *lp, SCIP_HEUR *heur)
Definition: sol.c:985
SCIP_RETCODE SCIPsolTransform(SCIP_SOL *sol, SCIP_SOL **transsol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal)
Definition: sol.c:658
SCIP_RETCODE SCIPsolSetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_VAR *var, SCIP_Real val)
Definition: sol.c:1490
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1908
SCIP_RETCODE SCIPsolUnlink(SCIP_SOL *sol, SCIP_SET *set, SCIP_PROB *prob)
Definition: sol.c:1431
void SCIPsolGetObjExact(SCIP_SOL *sol, SCIP_SET *set, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_RATIONAL *objval)
Definition: sol.c:2274
SCIP_Bool SCIPsolsAreEqual(SCIP_SOL *sol1, SCIP_SOL *sol2, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob)
Definition: sol.c:3370
SCIP_Real SCIPsolGetObj(SCIP_SOL *sol, SCIP_SET *set, SCIP_PROB *transprob, SCIP_PROB *origprob)
Definition: sol.c:2257
SCIP_RETCODE SCIPsolPrint(SCIP_SOL *sol, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_PROB *transprob, FILE *file, SCIP_Bool mipstart, SCIP_Bool printzeros)
Definition: sol.c:3441
void SCIPsolUpdateVarsum(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_Real weight)
Definition: sol.c:2942
SCIP_RETCODE SCIPsolCopy(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *primal, SCIP_SOL *sourcesol)
Definition: sol.c:583
SCIP_RETCODE SCIPsolCreate(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_HEUR *heur)
Definition: sol.c:428
SCIP_RETCODE SCIPsolUnlinkExact(SCIP_SOL *sol, SCIP_SET *set, SCIP_PROB *prob)
Definition: sol.c:1460
void SCIPsolOrigAddObjval(SCIP_SOL *sol, SCIP_Real addval)
Definition: sol.c:4193
internal methods for storing primal CIP solutions
internal methods for problem statistics
SCIP_LP * fplp
SCIP_LPEXACT * lpexact
Definition: struct_lp.h:309
SCIP_SOL * currentsol
Definition: struct_primal.h:63
int partialsolssize
Definition: struct_primal.h:67
int existingsolssize
Definition: struct_primal.h:70
SCIP_SOL ** partialsols
Definition: struct_primal.h:61
SCIP_SOL ** sols
Definition: struct_primal.h:60
SCIP_RATIONAL * cutoffboundexact
Definition: struct_primal.h:59
SCIP_Longint nlimbestsolsfound
Definition: struct_primal.h:53
SCIP_RATIONAL * upperboundexact
Definition: struct_primal.h:56
SCIP_Longint nbestsolsfound
Definition: struct_primal.h:52
SCIP_Bool updateviolations
Definition: struct_primal.h:73
SCIP_SOL * primalray
Definition: struct_primal.h:64
SCIP_Longint nsolsfound
Definition: struct_primal.h:49
SCIP_Longint nlimsolsfound
Definition: struct_primal.h:50
SCIP_Real cutoffbound
Definition: struct_primal.h:57
SCIP_SOL ** existingsols
Definition: struct_primal.h:62
SCIP_Real upperbound
Definition: struct_primal.h:55
SCIP_Longint nnodes
Definition: struct_stat.h:84
int firstprimaldepth
Definition: struct_stat.h:308
SCIP_VISUAL * visual
Definition: struct_stat.h:198
SCIP_Real firstprimaltime
Definition: struct_stat.h:136
int nrunsbeforefirst
Definition: struct_stat.h:307
SCIP_HEUR * firstprimalheur
Definition: struct_stat.h:200
SCIP_Longint nnodesbeforefirst
Definition: struct_stat.h:124
SCIP_Longint bestsolnode
Definition: struct_stat.h:115
SCIP_Real firstprimalbound
Definition: struct_stat.h:135
datastructures for managing events
data structures for exact LP management
Definition: heur_padm.c:135
SCIP_NODE * SCIPtreeGetCurrentNode(SCIP_TREE *tree)
Definition: tree.c:9462
SCIP_RETCODE SCIPtreeCutoff(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_Real cutoffbound)
Definition: tree.c:5858
int SCIPtreeGetCurrentDepth(SCIP_TREE *tree)
Definition: tree.c:9479
SCIP_Bool SCIPtreeInRepropagation(SCIP_TREE *tree)
Definition: tree.c:9452
internal methods for branch and bound tree
#define SCIP_EVENTTYPE_POORSOLFOUND
Definition: type_event.h:105
#define SCIP_EVENTTYPE_BESTSOLFOUND
Definition: type_event.h:106
@ SCIP_OBJSENSE_MINIMIZE
Definition: type_prob.h:48
@ SCIP_R_ROUND_UPWARDS
Definition: type_rational.h:58
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_OKAY
Definition: type_retcode.h:42
@ SCIP_INVALIDCALL
Definition: type_retcode.h:51
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_PROBLEM
Definition: type_set.h:45
@ SCIP_STAGE_SOLVING
Definition: type_set.h:53
@ SCIP_STAGE_PRESOLVED
Definition: type_set.h:51
@ SCIP_SOLORIGIN_ZERO
Definition: type_sol.h:43
@ SCIP_SOLORIGIN_ORIGINAL
Definition: type_sol.h:42
@ SCIP_VARSTATUS_FIXED
Definition: type_var.h:54
@ SCIP_VARSTATUS_MULTAGGR
Definition: type_var.h:56
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:18075
internal methods for problem variables
void SCIPvisualUpperbound(SCIP_VISUAL *visual, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real upperbound)
Definition: visual.c:805
void SCIPvisualFoundSolution(SCIP_VISUAL *visual, SCIP_SET *set, SCIP_STAT *stat, SCIP_NODE *node, SCIP_Bool bettersol, SCIP_SOL *sol)
Definition: visual.c:669
methods for creating output for visualization tools (VBC, BAK)