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/var.h"
42#include "scip/prob.h"
43#include "scip/sol.h"
44#include "scip/primal.h"
45#include "scip/tree.h"
46#include "scip/reopt.h"
47#include "scip/disp.h"
48#include "scip/struct_event.h"
49#include "scip/pub_message.h"
50#include "scip/pub_var.h"
52
53
54/*
55 * memory growing methods for dynamically allocated arrays
56 */
57
58/** ensures, that sols array can store at least num entries */
59static
61 SCIP_PRIMAL* primal, /**< primal data */
62 SCIP_SET* set, /**< global SCIP settings */
63 int num /**< minimum number of entries to store */
64 )
65{
66 assert(primal->nsols <= primal->solssize);
67
68 if( num > primal->solssize )
69 {
70 int newsize;
71
72 newsize = SCIPsetCalcMemGrowSize(set, num);
73 SCIP_ALLOC( BMSreallocMemoryArray(&primal->sols, newsize) );
74 primal->solssize = newsize;
75 }
76 assert(num <= primal->solssize);
77
78 return SCIP_OKAY;
79}
80
81/** ensures, that partialsols array can store at least num entries */
82static
84 SCIP_PRIMAL* primal, /**< primal data */
85 SCIP_SET* set, /**< global SCIP settings */
86 int num /**< minimum number of entries to store */
87 )
88{
89 assert(primal->npartialsols <= primal->partialsolssize);
90
91 if( num > primal->partialsolssize )
92 {
93 int newsize;
94
95 newsize = SCIPsetCalcMemGrowSize(set, num);
96 newsize = MIN(newsize, set->limit_maxorigsol);
97
98 SCIP_ALLOC( BMSreallocMemoryArray(&primal->partialsols, newsize) );
99 primal->partialsolssize = newsize;
100 }
101 assert(num <= primal->partialsolssize);
102
103 return SCIP_OKAY;
104}
105
106/** ensures, that existingsols array can store at least num entries */
107static
109 SCIP_PRIMAL* primal, /**< primal data */
110 SCIP_SET* set, /**< global SCIP settings */
111 int num /**< minimum number of entries to store */
112 )
113{
114 assert(primal->nexistingsols <= primal->existingsolssize);
115
116 if( num > primal->existingsolssize )
117 {
118 int newsize;
119
120 newsize = SCIPsetCalcMemGrowSize(set, num);
121 SCIP_ALLOC( BMSreallocMemoryArray(&primal->existingsols, newsize) );
122 primal->existingsolssize = newsize;
123 }
124 assert(num <= primal->existingsolssize);
125
126 return SCIP_OKAY;
127}
128
129/** creates primal data */
131 SCIP_PRIMAL** primal /**< pointer to primal data */
132 )
133{
134 assert(primal != NULL);
135
136 SCIP_ALLOC( BMSallocMemory(primal) );
137 (*primal)->sols = NULL;
138 (*primal)->partialsols = NULL;
139 (*primal)->existingsols = NULL;
140 (*primal)->currentsol = NULL;
141 (*primal)->primalray = NULL;
142 (*primal)->solssize = 0;
143 (*primal)->partialsolssize = 0;
144 (*primal)->nsols = 0;
145 (*primal)->npartialsols = 0;
146 (*primal)->existingsolssize = 0;
147 (*primal)->nexistingsols = 0;
148 (*primal)->nsolsfound = 0;
149 (*primal)->nlimsolsfound = 0;
150 (*primal)->nbestsolsfound = 0;
151 (*primal)->nlimbestsolsfound = 0;
152 (*primal)->upperbound = SCIP_INVALID;
153 (*primal)->cutoffbound = SCIP_INVALID;
154 (*primal)->updateviolations = TRUE;
155
156 return SCIP_OKAY;
157}
158
159/** frees primal data */
161 SCIP_PRIMAL** primal, /**< pointer to primal data */
162 BMS_BLKMEM* blkmem /**< block memory */
163 )
164{
165 assert(primal != NULL);
166 assert(*primal != NULL);
167
168 SCIP_CALL( SCIPprimalClear(*primal, blkmem) );
169
170 BMSfreeMemoryArrayNull(&(*primal)->sols);
171 BMSfreeMemoryArrayNull(&(*primal)->partialsols);
172 BMSfreeMemoryArrayNull(&(*primal)->existingsols);
173 BMSfreeMemory(primal);
174
175 return SCIP_OKAY;
176}
177
178/** clears primal data */
180 SCIP_PRIMAL* primal, /**< pointer to primal data */
181 BMS_BLKMEM* blkmem /**< block memory */
182 )
183{
184 int s;
185
186 assert(primal != NULL);
187
188 /* free temporary solution for storing current solution */
189 if( primal->currentsol != NULL )
190 {
191 SCIP_CALL( SCIPsolFree(&primal->currentsol, blkmem, primal) );
192 }
193
194 /* free solution for storing primal ray */
195 if( primal->primalray != NULL )
196 {
197 SCIP_CALL( SCIPsolFree(&primal->primalray, blkmem, primal) );
198 }
199
200 /* free feasible primal CIP solutions */
201 for( s = 0; s < primal->nsols; ++s )
202 {
203 SCIP_CALL( SCIPsolFree(&primal->sols[s], blkmem, primal) );
204 }
205
206 /* free partial CIP solutions */
207 for( s = 0; s < primal->npartialsols; ++s )
208 {
209 SCIP_CALL( SCIPsolFree(&primal->partialsols[s], blkmem, primal) );
210 }
211 assert(primal->nexistingsols == 0);
212
213 primal->currentsol = NULL;
214 primal->primalray = NULL;
215 primal->nsols = 0;
216 primal->nsolsfound = 0;
217 primal->npartialsols = 0;
218 primal->nlimsolsfound = 0;
219 primal->nbestsolsfound = 0;
220 primal->nlimbestsolsfound = 0;
221 primal->upperbound = SCIP_INVALID;
222 primal->cutoffbound = SCIP_INVALID;
223 primal->updateviolations = TRUE;
224
225 return SCIP_OKAY;
226}
227
228/** sorts primal solutions by objective value */
229static
231 SCIP_PRIMAL* primal, /**< primal data */
232 SCIP_SET* set, /**< global SCIP settings */
233 SCIP_PROB* origprob, /**< original problem */
234 SCIP_PROB* transprob /**< transformed problem */
235 )
236{
237 int i;
238
239 for( i = 1; i < primal->nsols; ++i )
240 {
241 SCIP_SOL* sol;
242 SCIP_Real objval;
243 int j;
244
245 sol = primal->sols[i];
246 objval = SCIPsolGetObj(sol, set, transprob, origprob);
247 for( j = i; j > 0 && objval < SCIPsolGetObj(primal->sols[j-1], set, transprob, origprob); --j )
248 primal->sols[j] = primal->sols[j-1];
249 primal->sols[j] = sol;
250 }
251
252 return;
253}
254
255/** sets the cutoff bound in primal data and in LP solver */
256static
258 SCIP_PRIMAL* primal, /**< primal data */
259 BMS_BLKMEM* blkmem, /**< block memory */
260 SCIP_SET* set, /**< global SCIP settings */
261 SCIP_STAT* stat, /**< problem statistics data */
262 SCIP_PROB* prob, /**< problem data */
263 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
264 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
265 SCIP_TREE* tree, /**< branch and bound tree */
266 SCIP_REOPT* reopt, /**< reoptimization data structure */
267 SCIP_LP* lp, /**< current LP data */
268 SCIP_Real cutoffbound /**< new cutoff bound */
269 )
270{
271 assert(primal != NULL);
272 assert(cutoffbound <= SCIPsetInfinity(set));
273 assert(primal->upperbound == SCIP_INVALID || SCIPsetIsLE(set, cutoffbound, primal->upperbound)); /*lint !e777*/
274 assert(!SCIPtreeInRepropagation(tree));
275
276 SCIPsetDebugMsg(set, "changing cutoff bound from %g to %g\n", primal->cutoffbound, cutoffbound);
277
278 primal->cutoffbound = MIN(cutoffbound, primal->upperbound); /* get rid of numerical issues */
279
280 /* set cut off value in LP solver */
281 SCIP_CALL( SCIPlpSetCutoffbound(lp, set, prob, primal->cutoffbound) );
282
283 /* cut off leaves of the tree */
284 SCIP_CALL( SCIPtreeCutoff(tree, reopt, blkmem, set, stat, eventfilter, eventqueue, lp, primal->cutoffbound) );
285
286 return SCIP_OKAY;
287}
288
289/** sets the cutoff bound in primal data and in LP solver */
291 SCIP_PRIMAL* primal, /**< primal data */
292 BMS_BLKMEM* blkmem, /**< block memory */
293 SCIP_SET* set, /**< global SCIP settings */
294 SCIP_STAT* stat, /**< problem statistics data */
295 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
296 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
297 SCIP_PROB* transprob, /**< transformed problem data */
298 SCIP_PROB* origprob, /**< original problem data */
299 SCIP_TREE* tree, /**< branch and bound tree */
300 SCIP_REOPT* reopt, /**< reoptimization data structure */
301 SCIP_LP* lp, /**< current LP data */
302 SCIP_Real cutoffbound, /**< new cutoff bound */
303 SCIP_Bool useforobjlimit /**< should the cutoff bound be used to update the objective limit, if
304 * better? */
305 )
306{
307 assert(primal != NULL);
308 assert(cutoffbound <= SCIPsetInfinity(set));
309 assert(cutoffbound <= primal->upperbound);
310 assert(transprob != NULL);
311 assert(origprob != NULL);
312
313 if( cutoffbound < primal->cutoffbound )
314 {
315 if( useforobjlimit )
316 {
317 SCIP_Real objval;
318
319 objval = SCIPprobExternObjval(transprob, origprob, set, cutoffbound);
320
321 if( objval < SCIPprobGetObjlim(origprob, set) )
322 {
323 SCIPsetDebugMsg(set, "changing cutoff bound from %g to %g changes objective limit from %g to %g\n",
324 primal->cutoffbound, cutoffbound, SCIPprobGetObjlim(origprob, set), objval);
325 SCIPprobSetObjlim(origprob, objval);
326 SCIPprobSetObjlim(transprob, objval);
327 }
328 }
329
330 /* update cutoff bound */
331 SCIP_CALL( primalSetCutoffbound(primal, blkmem, set, stat, transprob, eventfilter, eventqueue, tree, reopt, lp, cutoffbound) );
332 }
333 else if( cutoffbound > primal->cutoffbound )
334 {
335 SCIPerrorMessage("invalid increase in cutoff bound\n");
336 return SCIP_INVALIDDATA;
337 }
338
339 return SCIP_OKAY;
340}
341
342/** sets upper bound in primal data and in LP solver */
343static
345 SCIP_PRIMAL* primal, /**< primal data */
346 BMS_BLKMEM* blkmem, /**< block memory */
347 SCIP_SET* set, /**< global SCIP settings */
348 SCIP_STAT* stat, /**< problem statistics data */
349 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
350 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
351 SCIP_PROB* prob, /**< transformed problem after presolve */
352 SCIP_TREE* tree, /**< branch and bound tree */
353 SCIP_REOPT* reopt, /**< reoptimization data structure */
354 SCIP_LP* lp, /**< current LP data */
355 SCIP_Real upperbound /**< new upper bound */
356 )
357{
358 SCIP_Real cutoffbound;
359
360 assert(primal != NULL);
361 assert(stat != NULL);
362 assert(upperbound <= SCIPsetInfinity(set));
363 assert(upperbound <= primal->upperbound || stat->nnodes == 0);
364
365 SCIPsetDebugMsg(set, "changing upper bound from %g to %g\n", primal->upperbound, upperbound);
366
367 primal->upperbound = upperbound;
368
369 /* if objective value is always integral, the cutoff bound can be reduced to nearly the previous integer number */
370 if( SCIPprobIsObjIntegral(prob) && !SCIPsetIsInfinity(set, upperbound) )
371 {
372 SCIP_Real delta;
373
375
376 cutoffbound = SCIPsetFeasCeil(set, upperbound) - (1.0 - delta);
377 cutoffbound = MIN(cutoffbound, upperbound); /* SCIPsetFeasCeil() can increase bound by almost 1.0 due to numerics
378 * and very large upperbound value */
379 }
380 else
381 cutoffbound = upperbound;
382
383 /* update cutoff bound */
384 if( cutoffbound < primal->cutoffbound )
385 {
386 SCIP_CALL( primalSetCutoffbound(primal, blkmem, set, stat, prob, eventfilter, eventqueue, tree, reopt, lp, cutoffbound) );
387 }
388
389 /* update upper bound in visualization output */
390 if( SCIPtreeGetCurrentDepth(tree) >= 0 )
391 {
392 SCIPvisualUpperbound(stat->visual, set, stat, primal->upperbound);
393 }
394
395 return SCIP_OKAY;
396}
397
398/** sets upper bound in primal data and in LP solver */
400 SCIP_PRIMAL* primal, /**< primal data */
401 BMS_BLKMEM* blkmem, /**< block memory */
402 SCIP_SET* set, /**< global SCIP settings */
403 SCIP_STAT* stat, /**< problem statistics data */
404 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
405 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
406 SCIP_PROB* prob, /**< transformed problem after presolve */
407 SCIP_TREE* tree, /**< branch and bound tree */
408 SCIP_REOPT* reopt, /**< reoptimization data structure */
409 SCIP_LP* lp, /**< current LP data */
410 SCIP_Real upperbound /**< new upper bound */
411 )
412{
413 assert(primal != NULL);
414 assert(upperbound <= SCIPsetInfinity(set));
415
416 if( upperbound < primal->upperbound )
417 {
418 /* update primal bound */
419 SCIP_CALL( primalSetUpperbound(primal, blkmem, set, stat, eventfilter, eventqueue, prob, tree, reopt, lp, upperbound) );
420 }
421 else if( upperbound > primal->upperbound )
422 {
423 SCIPerrorMessage("invalid increase in upper bound\n");
424 return SCIP_INVALIDDATA;
425 }
426
427 return SCIP_OKAY;
428}
429
430/** updates upper bound and cutoff bound in primal data after a tightening of the problem's objective limit */
432 SCIP_PRIMAL* primal, /**< primal data */
433 BMS_BLKMEM* blkmem, /**< block memory */
434 SCIP_SET* set, /**< global SCIP settings */
435 SCIP_STAT* stat, /**< problem statistics data */
436 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
437 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
438 SCIP_PROB* transprob, /**< transformed problem data */
439 SCIP_PROB* origprob, /**< original problem data */
440 SCIP_TREE* tree, /**< branch and bound tree */
441 SCIP_REOPT* reopt, /**< reoptimization data structure */
442 SCIP_LP* lp /**< current LP data */
443 )
444{
445 SCIP_Real objlimit;
446 SCIP_Real inf;
447
448 assert(primal != NULL);
449
450 /* get internal objective limit */
451 objlimit = SCIPprobInternObjval(transprob, origprob, set, SCIPprobGetObjlim(origprob, set));
452 inf = SCIPsetInfinity(set);
453 objlimit = MIN(objlimit, inf);
454
455 /* update the cutoff bound */
456 if( objlimit < primal->cutoffbound )
457 {
458 SCIP_CALL( primalSetCutoffbound(primal, blkmem, set, stat, transprob, eventfilter, eventqueue, tree, reopt, lp, objlimit) );
459 }
460
461 /* set new upper bound (and decrease cutoff bound, if objective value is always integral) */
462 if( objlimit < primal->upperbound )
463 {
464 SCIP_CALL( primalSetUpperbound(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, tree, reopt, lp, objlimit) );
465 }
466
467 return SCIP_OKAY;
468}
469
470/** recalculates upper bound and cutoff bound in primal data after a change of the problem's objective offset */
472 SCIP_PRIMAL* primal, /**< primal data */
473 BMS_BLKMEM* blkmem, /**< block memory */
474 SCIP_SET* set, /**< global SCIP settings */
475 SCIP_STAT* stat, /**< problem statistics data */
476 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
477 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
478 SCIP_PROB* transprob, /**< tranformed problem data */
479 SCIP_PROB* origprob, /**< original problem data */
480 SCIP_TREE* tree, /**< branch and bound tree */
481 SCIP_REOPT* reopt, /**< reoptimization data structure */
482 SCIP_LP* lp /**< current LP data */
483 )
484{
485 SCIP_Real upperbound;
486 SCIP_Real inf;
487
488 assert(primal != NULL);
490
491 /* recalculate internal objective limit */
492 upperbound = SCIPprobInternObjval(transprob, origprob, set, SCIPprobGetObjlim(origprob, set));
493 inf = SCIPsetInfinity(set);
494 upperbound = MIN(upperbound, inf);
495
496 /* resort current primal solutions */
497 sortPrimalSols(primal, set, origprob, transprob);
498
499 /* compare objective limit to currently best solution */
500 if( primal->nsols > 0 )
501 {
502 SCIP_Real obj;
503
504 assert(SCIPsolIsOriginal(primal->sols[0]));
505 obj = SCIPsolGetObj(primal->sols[0], set, transprob, origprob);
506
507 upperbound = MIN(upperbound, obj);
508 }
509
510 /* invalidate old upper bound */
511 SCIP_CALL( primalSetUpperbound(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, tree, reopt, lp, SCIPsetInfinity(set)) );
512
513 /* reset the cutoff bound
514 *
515 * @note we might need to relax the bound since in presolving the objective correction of an
516 * aggregation is still in progress
517 */
518 SCIP_CALL( primalSetCutoffbound(primal, blkmem, set, stat, transprob, eventfilter, eventqueue, tree, reopt, lp, upperbound) );
519
520 /* set new upper bound (and decrease cutoff bound, if objective value is always integral) */
521 SCIP_CALL( primalSetUpperbound(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, tree, reopt, lp, upperbound) );
522
523 return SCIP_OKAY;
524}
525
526/** adds additional objective offset in original space to all existing solution (in original space) */
528 SCIP_PRIMAL* primal, /**< primal data */
529 SCIP_SET* set, /**< global SCIP settings */
530 SCIP_Real addval /**< additional objective offset in original space */
531 )
532{
533 int i;
534
535 assert(primal != NULL);
536 assert(set != NULL);
538
539#ifndef NDEBUG
540 assert(primal->nsols == 0 || SCIPsolGetOrigin(primal->sols[0]) == SCIP_SOLORIGIN_ORIGINAL);
541
542 /* check current order of primal solutions */
543 for( i = 1; i < primal->nsols; ++i )
544 {
545 assert(SCIPsolGetOrigin(primal->sols[i]) == SCIP_SOLORIGIN_ORIGINAL);
546 assert(SCIPsetIsLE(set, SCIPsolGetOrigObj(primal->sols[i-1]), SCIPsolGetOrigObj(primal->sols[i])));
547 }
548#endif
549
550 /* check current order of primal solutions */
551 for( i = 0; i < primal->nexistingsols; ++i )
552 {
553 assert(primal->existingsols[i] != NULL);
554 SCIPsolOrigAddObjval(primal->existingsols[i], addval);
555 }
556}
557
558/** returns whether the current primal bound is justified with a feasible primal solution; if not, the primal bound
559 * was set from the user as objective limit
560 */
562 SCIP_PRIMAL* primal, /**< primal data */
563 SCIP_SET* set, /**< global SCIP settings */
564 SCIP_PROB* transprob, /**< tranformed problem data */
565 SCIP_PROB* origprob /**< original problem data */
566 )
567{
568 assert(primal != NULL);
569
570 return (primal->nsols > 0 && SCIPsetIsEQ(set, primal->upperbound, SCIPsolGetObj(primal->sols[0], set, transprob, origprob)));
571}
572
573/** returns the primal ray thats proves unboundedness */
575 SCIP_PRIMAL* primal /**< primal data */
576 )
577{
578 assert(primal != NULL);
579
580 return primal->primalray;
581}
582
583/** update the primal ray thats proves unboundedness */
585 SCIP_PRIMAL* primal, /**< primal data */
586 SCIP_SET* set, /**< global SCIP settings */
587 SCIP_STAT* stat, /**< dynamic SCIP statistics */
588 SCIP_SOL* primalray, /**< the new primal ray */
589 BMS_BLKMEM* blkmem /**< block memory */
590 )
591{
592 assert(primal != NULL);
593 assert(set != NULL);
594 assert(stat != NULL);
595 assert(primalray != NULL);
596 assert(blkmem != NULL);
597
598 /* clear previously stored primal ray, if any */
599 if( primal->primalray != NULL )
600 {
601 SCIP_CALL( SCIPsolFree(&primal->primalray, blkmem, primal) );
602 }
603
604 assert(primal->primalray == NULL);
605
606 SCIP_CALL( SCIPsolCopy(&primal->primalray, blkmem, set, stat, primal, primalray) );
607
608 return SCIP_OKAY;
609}
610
611/** adds primal solution to solution storage at given position */
612static
614 SCIP_PRIMAL* primal, /**< primal data */
615 BMS_BLKMEM* blkmem, /**< block memory */
616 SCIP_SET* set, /**< global SCIP settings */
617 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
618 SCIP_STAT* stat, /**< problem statistics data */
619 SCIP_PROB* origprob, /**< original problem */
620 SCIP_PROB* transprob, /**< transformed problem after presolve */
621 SCIP_TREE* tree, /**< branch and bound tree */
622 SCIP_REOPT* reopt, /**< reoptimization data structure */
623 SCIP_LP* lp, /**< current LP data */
624 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
625 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
626 SCIP_SOL** solptr, /**< pointer to primal CIP solution */
627 int insertpos, /**< position in solution storage to add solution to */
628 SCIP_Bool replace /**< should the solution at insertpos be replaced by the new solution? */
629 )
630{
631 SCIP_SOL* sol;
632 SCIP_EVENT event;
633 SCIP_Real obj;
634 int pos;
635
636 assert(primal != NULL);
637 assert(set != NULL);
638 assert(solptr != NULL);
639 assert(stat != NULL);
640 assert(transprob != NULL);
641 assert(origprob != NULL);
642 assert(0 <= insertpos && insertpos < set->limit_maxsol);
643 assert(tree == NULL || !SCIPtreeInRepropagation(tree));
644
645 sol = *solptr;
646 assert(sol != NULL);
647
648 /* if the solution is added during presolving and it is not defined on original variables,
649 * presolving operations will destroy its validity, so we retransform it to the original space
650 */
651 if( set->stage < SCIP_STAGE_PRESOLVED && !SCIPsolIsOriginal(sol) )
652 {
653 SCIP_Bool hasinfval;
654
655 SCIP_CALL( SCIPsolUnlink(sol, set, transprob) );
656 SCIP_CALL( SCIPsolRetransform(sol, set, stat, origprob, transprob, &hasinfval) );
657 }
658
659 obj = SCIPsolGetObj(sol, set, transprob, origprob);
660
661 SCIPsetDebugMsg(set, "insert primal solution %p with obj %g at position %d (replace=%u):\n",
662 (void*)sol, obj, insertpos, replace);
663
664 /* make sure that the primal bound is at least the lower bound */
666 {
668 {
669 SCIPmessagePrintWarning(messagehdlr, "Dual bound %g is larger than the objective of the primal solution %g. The solution might not be optimal.\n",
670 SCIPprobExternObjval(transprob, origprob, set, SCIPgetLowerbound(set->scip)), SCIPprobExternObjval(transprob, origprob, set, obj));
671 }
672 else
673 {
674 SCIPmessagePrintWarning(messagehdlr, "Dual bound %g is smaller than the objective of the primal solution %g. The solution might not be optimal.\n",
675 SCIPprobExternObjval(transprob, origprob, set, SCIPgetLowerbound(set->scip)), SCIPprobExternObjval(transprob, origprob, set, obj));
676 }
677
678#ifdef WITH_DEBUG_SOLUTION
679 /* check for missed debugsol cutoff */
680 if( SCIPdebugSolIsEnabled(set->scip) )
681 {
682 SCIP_SOL* debugsol;
683
684 SCIPdebugGetSol(set->scip, &debugsol);
685
687 assert(SCIPsetIsFeasLE(set, SCIPgetDualbound(set->scip), SCIPsolGetOrigObj(debugsol)));
688 else
689 assert(SCIPsetIsFeasGE(set, SCIPgetDualbound(set->scip), SCIPsolGetOrigObj(debugsol)));
690 }
691#endif
692 }
693
694 SCIPdebug( SCIP_CALL( SCIPsolPrint(sol, set, messagehdlr, stat, transprob, NULL, NULL, FALSE, FALSE) ) );
695
696#ifdef SCIP_DISABLED_CODE
697 /* this is not a valid debug check, but can be used to track down numerical troubles */
698#ifndef NDEBUG
699 /* check solution again completely
700 * it fail for different reasons:
701 * - in the LP solver, the feasibility tolerance is a relative measure against the row's norm
702 * - in SCIP, the feasibility tolerance is a relative measure against the row's rhs/lhs
703 * - the rhs/lhs of a row might drastically change during presolving when variables are fixed or (multi-)aggregated
704 */
705 if( !SCIPsolIsOriginal(sol) )
706 {
707 SCIP_Bool feasible;
708
709 SCIP_CALL( SCIPsolCheck(sol, set, messagehdlr, blkmem, stat, transprob, TRUE, TRUE, TRUE, TRUE, &feasible) );
710
711 if( !feasible )
712 {
713 SCIPerrorMessage("infeasible solution accepted:\n");
714 SCIP_CALL( SCIPsolPrint(sol, set, messagehdlr, stat, origprob, transprob, NULL, FALSE, FALSE) );
715 }
716 assert(feasible);
717 }
718#endif
719#endif
720
721 /* completely fill the solution's own value array to unlink it from the LP or pseudo solution */
722 SCIP_CALL( SCIPsolUnlink(sol, set, transprob) );
723
724 /* allocate memory for solution storage */
725 SCIP_CALL( ensureSolsSize(primal, set, set->limit_maxsol) );
726
727 /* if set->limit_maxsol was decreased in the meantime, free all solutions exceeding the limit */
728 for( pos = set->limit_maxsol; pos < primal->nsols; ++pos )
729 {
730 SCIP_CALL( SCIPsolFree(&primal->sols[pos], blkmem, primal) );
731 }
732 primal->nsols = MIN(primal->nsols, set->limit_maxsol);
733
734 /* if the solution should replace an existing one, free this solution, otherwise,
735 * free the last solution if the solution storage is full;
736 */
737 if( replace )
738 {
739 SCIP_CALL( SCIPsolTransform(primal->sols[insertpos], solptr, blkmem, set, primal) );
740 sol = primal->sols[insertpos];
741 }
742 else
743 {
744 if( primal->nsols == set->limit_maxsol ) /* cppcheck-suppress knownConditionTrueFalse */
745 {
746 SCIP_CALL( SCIPsolFree(&primal->sols[set->limit_maxsol - 1], blkmem, primal) );
747 }
748 else
749 {
750 primal->nsols = primal->nsols + 1;
751 assert(primal->nsols <= set->limit_maxsol);
752 }
753
754 /* move all solutions with worse objective value than the new solution */
755 for( pos = primal->nsols-1; pos > insertpos; --pos )
756 primal->sols[pos] = primal->sols[pos-1];
757
758 /* insert solution at correct position */
759 assert(0 <= insertpos && insertpos < primal->nsols);
760 primal->sols[insertpos] = sol;
761 primal->nsolsfound++;
762
763 /* check if solution is better than objective limit */
764 if( SCIPsetIsFeasLE(set, obj, SCIPprobInternObjval(transprob, origprob, set, SCIPprobGetObjlim(origprob, set))) )
765 primal->nlimsolsfound++;
766 }
767
768 /* if its the first primal solution, store the relevant statistics */
769 if( primal->nsolsfound == 1 )
770 {
771 SCIP_Real primalsolval;
772
775 stat->firstprimalheur = SCIPsolGetHeur(sol);
776 stat->firstprimaltime = SCIPsolGetTime(sol);
778
779 primalsolval = obj;
780 stat->firstprimalbound = SCIPprobExternObjval(transprob, origprob, set, primalsolval);
781
782 SCIPsetDebugMsg(set, "First Solution stored in problem specific statistics.\n");
783 SCIPsetDebugMsg(set, "-> %" SCIP_LONGINT_FORMAT " nodes, %d runs, %.2g time, %d depth, %.15g objective\n", stat->nnodesbeforefirst, stat->nrunsbeforefirst,
785 }
786
787 SCIPsetDebugMsg(set, " -> stored at position %d of %d solutions, found %" SCIP_LONGINT_FORMAT " solutions\n",
788 insertpos, primal->nsols, primal->nsolsfound);
789
790 /* update the solution value sums in variables */
791 if( !SCIPsolIsOriginal(sol) )
792 {
793 SCIPsolUpdateVarsum(sol, set, stat, transprob,
794 (SCIP_Real)(primal->nsols - insertpos)/(SCIP_Real)(2.0*primal->nsols - 1.0));
795 }
796
797 /* change color of node in visualization output */
798 SCIPvisualFoundSolution(stat->visual, set, stat, SCIPtreeGetCurrentNode(tree), insertpos == 0 ? TRUE : FALSE, sol);
799
800 /* check, if the global upper bound has to be updated */
801 if( obj < primal->cutoffbound && insertpos == 0 )
802 {
803 /* issue BESTSOLFOUND event */
805 SCIP_CALL( SCIPeventChgSol(&event, sol) );
806 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
807
808 /* update the upper bound */
809 SCIP_CALL( SCIPprimalSetUpperbound(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, tree, reopt, lp, obj) );
810
811 primal->nbestsolsfound++;
812 stat->bestsolnode = stat->nnodes;
813 }
814 else
815 {
816 /* issue POORSOLFOUND event */
818 SCIP_CALL( SCIPeventChgSol(&event, sol) );
819 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
820 }
821
822
823 /* display node information line */
824 if( insertpos == 0 && !replace && set->stage >= SCIP_STAGE_SOLVING )
825 {
826 SCIP_CALL( SCIPdispPrintLine(set, messagehdlr, stat, NULL, TRUE, TRUE) );
827 }
828
829 /* if an original solution was added during solving, try to transfer it to the transformed space */
830 if( SCIPsolIsOriginal(sol) && SCIPsetGetStage(set) == SCIP_STAGE_SOLVING && set->misc_transorigsols )
831 {
832 SCIP_Bool added;
833
834 SCIP_CALL( SCIPprimalTransformSol(primal, sol, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt,
835 lp, eventqueue, eventfilter, NULL, NULL, 0, &added) );
836
837 SCIPsetDebugMsg(set, "original solution %p was successfully transferred to the transformed problem space\n",
838 (void*)sol);
839 } /*lint !e438*/
840
841 return SCIP_OKAY;
842}
843
844/** adds primal solution to solution storage at given position */
845static
847 SCIP_PRIMAL* primal, /**< primal data */
848 BMS_BLKMEM* blkmem, /**< block memory */
849 SCIP_SET* set, /**< global SCIP settings */
850 SCIP_PROB* prob, /**< original problem data */
851 SCIP_SOL* sol, /**< primal CIP solution */
852 int insertpos /**< position in solution storage to add solution to */
853 )
854{
855 int pos;
856
857 assert(primal != NULL);
858 assert(set != NULL);
859 assert(prob != NULL);
860 assert(sol != NULL);
861 assert(0 <= insertpos && insertpos < set->limit_maxorigsol);
862 assert(!set->reopt_enable);
863
864 SCIPsetDebugMsg(set, "insert primal solution candidate %p with obj %g at position %d:\n", (void*)sol, SCIPsolGetOrigObj(sol), insertpos);
865
866 /* allocate memory for solution storage */
867 SCIP_CALL( ensureSolsSize(primal, set, set->limit_maxorigsol) );
868
869 /* if the solution storage is full, free the last solution(s)
870 * more than one solution may be freed, if set->limit_maxorigsol was decreased in the meantime
871 */
872 for( pos = set->limit_maxorigsol-1; pos < primal->nsols; ++pos )
873 {
874 SCIP_CALL( SCIPsolFree(&primal->sols[pos], blkmem, primal) );
875 }
876
877 /* insert solution at correct position */
878 primal->nsols = MIN(primal->nsols+1, set->limit_maxorigsol);
879 for( pos = primal->nsols-1; pos > insertpos; --pos )
880 primal->sols[pos] = primal->sols[pos-1];
881
882 assert(0 <= insertpos && insertpos < primal->nsols);
883 primal->sols[insertpos] = sol;
884 primal->nsolsfound++;
885
886 /* check if solution is better than objective limit */
888 primal->nlimsolsfound++;
889
890 SCIPsetDebugMsg(set, " -> stored at position %d of %d solutions, found %" SCIP_LONGINT_FORMAT " solutions\n",
891 insertpos, primal->nsols, primal->nsolsfound);
892
893 return SCIP_OKAY;
894}
895
896/** adds primal solution to solution storage */
897static
899 SCIP_PRIMAL* primal, /**< primal data */
900 SCIP_SET* set, /**< global SCIP settings */
901 SCIP_PROB* prob, /**< original problem data */
902 SCIP_SOL* sol /**< primal CIP solution */
903 )
904{ /*lint --e{715}*/
905 assert(primal != NULL);
906 assert(set != NULL);
907 assert(prob != NULL);
908 assert(sol != NULL);
909
910 if( primal->npartialsols >= set->limit_maxorigsol )
911 {
912 SCIPerrorMessage("Cannot add partial solution to storage: limit reached.\n");
913 return SCIP_INVALIDCALL;
914 }
915
916 SCIPsetDebugMsg(set, "insert partial solution candidate %p:\n", (void*)sol);
917
918 /* allocate memory for solution storage */
919 SCIP_CALL( ensurePartialsolsSize(primal, set, primal->npartialsols+1) );
920
921 primal->partialsols[primal->npartialsols] = sol;
922 ++primal->npartialsols;
923
924 return SCIP_OKAY;
925}
926
927/** uses binary search to find position in solution storage */
928static
930 SCIP_PRIMAL* primal, /**< primal data */
931 SCIP_SET* set, /**< global SCIP settings */
932 SCIP_PROB* transprob, /**< tranformed problem data */
933 SCIP_PROB* origprob, /**< original problem data */
934 SCIP_SOL* sol /**< primal solution to search position for */
935 )
936{
937 SCIP_SOL** sols;
938 SCIP_Real obj;
939 SCIP_Real middleobj;
940 int left;
941 int right;
942 int middle;
943
944 assert(primal != NULL);
945
946 obj = SCIPsolGetObj(sol, set, transprob, origprob);
947 sols = primal->sols;
948
949 left = -1;
950 right = primal->nsols;
951 while( left < right-1 )
952 {
953 middle = (left+right)/2;
954 assert(left < middle && middle < right);
955 assert(0 <= middle && middle < primal->nsols);
956
957 middleobj = SCIPsolGetObj(sols[middle], set, transprob, origprob);
958
959 if( obj < middleobj )
960 right = middle;
961 else
962 left = middle;
963 }
964 assert(left == right-1);
965
966 /* prefer solutions that live in the transformed space */
967 if( !SCIPsolIsOriginal(sol) )
968 {
969 while( right > 0 && SCIPsolIsOriginal(sols[right-1])
970 && SCIPsetIsEQ(set, SCIPsolGetObj(sols[right-1], set, transprob, origprob), obj) )
971 --right;
972 }
973
974 return right;
975}
976
977/** uses binary search to find position in solution storage */
978static
980 SCIP_PRIMAL* primal, /**< primal data */
981 SCIP_SOL* sol /**< primal solution to search position for */
982 )
983{
984 SCIP_Real obj;
985 SCIP_Real middleobj;
986 int left;
987 int right;
988 int middle;
989
990 assert(primal != NULL);
991
992 obj = SCIPsolGetOrigObj(sol);
993
994 left = -1;
995 right = primal->nsols;
996 while( left < right-1 )
997 {
998 middle = (left+right)/2;
999 assert(left < middle && middle < right);
1000 assert(0 <= middle && middle < primal->nsols);
1001 middleobj = SCIPsolGetOrigObj(primal->sols[middle]);
1002 if( obj < middleobj )
1003 right = middle;
1004 else
1005 left = middle;
1006 }
1007 assert(left == right-1);
1008
1009 return right;
1010}
1011
1012/** returns whether the given primal solution is already existent in the solution storage */
1013static
1015 SCIP_PRIMAL* primal, /**< primal data */
1016 SCIP_SET* set, /**< global SCIP settings */
1017 SCIP_STAT* stat, /**< problem statistics data */
1018 SCIP_PROB* origprob, /**< original problem */
1019 SCIP_PROB* transprob, /**< transformed problem after presolve */
1020 SCIP_SOL* sol, /**< primal solution to search position for */
1021 int* insertpos, /**< pointer to insertion position returned by primalSearchSolPos(); the
1022 * position might be changed if an existing solution should be replaced */
1023 SCIP_Bool* replace /**< pointer to store whether the solution at insertpos should be replaced */
1024 )
1025{
1026 SCIP_Real obj;
1027 int i;
1028
1029 assert(primal != NULL);
1030 assert(insertpos != NULL);
1031 assert(replace != NULL);
1032 assert(0 <= (*insertpos) && (*insertpos) <= primal->nsols);
1033
1034 obj = SCIPsolGetObj(sol, set, transprob, origprob);
1035
1036 assert(primal->sols != NULL || primal->nsols == 0);
1037 assert(primal->sols != NULL || (*insertpos) == 0);
1038
1039 /* search in the better solutions */
1040 for( i = (*insertpos)-1; i >= 0; --i )
1041 {
1042 SCIP_Real solobj;
1043
1044 solobj = SCIPsolGetObj(primal->sols[i], set, transprob, origprob);
1045
1046 /* due to transferring the objective value of transformed solutions to the original space, small numerical errors might occur
1047 * which can lead to SCIPsetIsLE() failing in case of high absolute numbers
1048 */
1049 assert(SCIPsetIsLE(set, solobj, obj) || (REALABS(obj) > 1e+13 * SCIPsetEpsilon(set) && SCIPsetIsFeasLE(set, solobj, obj)));
1050
1051 if( SCIPsetIsLT(set, solobj, obj) )
1052 break;
1053
1054 if( SCIPsolsAreEqual(sol, primal->sols[i], set, stat, origprob, transprob) )
1055 {
1056 if( set->stage >= SCIP_STAGE_PRESOLVED && SCIPsolIsOriginal(primal->sols[i]) && !SCIPsolIsOriginal(sol) )
1057 {
1058 (*insertpos) = i;
1059 (*replace) = TRUE;
1060 }
1061 return TRUE;
1062 }
1063 }
1064
1065 /* search in the worse solutions */
1066 for( i = (*insertpos); i < primal->nsols; ++i )
1067 {
1068 SCIP_Real solobj;
1069
1070 solobj = SCIPsolGetObj(primal->sols[i], set, transprob, origprob);
1071
1072 /* due to transferring the objective value of transformed solutions to the original space, small numerical errors might occur
1073 * which can lead to SCIPsetIsLE() failing in case of high absolute numbers
1074 */
1075 assert( SCIPsetIsGE(set, solobj, obj) || (REALABS(obj) > 1e+13 * SCIPsetEpsilon(set) && SCIPsetIsFeasGE(set, solobj, obj)));
1076
1077 if( SCIPsetIsGT(set, solobj, obj) )
1078 break;
1079
1080 if( SCIPsolsAreEqual(sol, primal->sols[i], set, stat, origprob, transprob) )
1081 {
1082 if( set->stage >= SCIP_STAGE_PRESOLVED && SCIPsolIsOriginal(primal->sols[i]) && !SCIPsolIsOriginal(sol) )
1083 {
1084 (*insertpos) = i;
1085 (*replace) = TRUE;
1086 }
1087 return TRUE;
1088 }
1089 }
1090
1091 return FALSE;
1092}
1093
1094/** returns whether the given primal solution is already existent in the original solution candidate storage */
1095static
1097 SCIP_PRIMAL* primal, /**< primal data */
1098 SCIP_SET* set, /**< global SCIP settings */
1099 SCIP_STAT* stat, /**< problem statistics data */
1100 SCIP_PROB* prob, /**< original problem */
1101 SCIP_SOL* sol, /**< primal solution to search position for */
1102 int insertpos /**< insertion position returned by primalSearchOrigSolPos() */
1103 )
1104{
1105 SCIP_Real obj;
1106 int i;
1107
1108 assert(primal != NULL);
1109 assert(0 <= insertpos && insertpos <= primal->nsols);
1110
1111 obj = SCIPsolGetOrigObj(sol);
1112
1113 /* search in the better solutions */
1114 for( i = insertpos-1; i >= 0; --i )
1115 {
1116 SCIP_Real solobj;
1117
1118 solobj = SCIPsolGetOrigObj(primal->sols[i]);
1119 assert( SCIPsetIsLE(set, solobj, obj) );
1120
1121 if( SCIPsetIsLT(set, solobj, obj) )
1122 break;
1123
1124 if( SCIPsolsAreEqual(sol, primal->sols[i], set, stat, prob, NULL) )
1125 return TRUE;
1126 }
1127
1128 /* search in the worse solutions */
1129 for( i = insertpos; i < primal->nsols; ++i )
1130 {
1131 SCIP_Real solobj;
1132
1133 solobj = SCIPsolGetOrigObj(primal->sols[i]);
1134 assert( SCIPsetIsGE(set, solobj, obj) );
1135
1136 if( SCIPsetIsGT(set, solobj, obj) )
1137 break;
1138
1139 if( SCIPsolsAreEqual(sol, primal->sols[i], set, stat, prob, NULL) )
1140 return TRUE;
1141 }
1142
1143 return FALSE;
1144}
1145
1146/** check if we are willing to check the solution for feasibility */
1147static
1149 SCIP_PRIMAL* primal, /**< primal data */
1150 SCIP_SET* set, /**< global SCIP settings */
1151 SCIP_STAT* stat, /**< problem statistics data */
1152 SCIP_PROB* origprob, /**< original problem */
1153 SCIP_PROB* transprob, /**< transformed problem after presolve */
1154 SCIP_SOL* sol, /**< primal CIP solution */
1155 int* insertpos, /**< pointer to store the insert position of that solution */
1156 SCIP_Bool* replace /**< pointer to store whether the solution at insertpos should be replaced
1157 * (e.g., because it lives in the original space) */
1158 )
1159{
1160 SCIP_Real obj;
1161
1162 obj = SCIPsolGetObj(sol, set, transprob, origprob);
1163
1164 /* check if we are willing to check worse solutions; a solution is better if the objective is smaller than the
1165 * current cutoff bound; solutions with infinite objective value are never accepted
1166 */
1167 if( (!set->misc_improvingsols || obj < primal->cutoffbound) && !SCIPsetIsInfinity(set, obj) )
1168 {
1169 /* find insert position for the solution */
1170 (*insertpos) = primalSearchSolPos(primal, set, transprob, origprob, sol);
1171 (*replace) = FALSE;
1172
1173 /* the solution should be added, if the insertpos is smaller than the maximum number of solutions to be stored
1174 * and it does not already exist or it does exist, but the existing solution should be replaced by the new one
1175 */
1176 if( (*insertpos) < set->limit_maxsol &&
1177 (!primalExistsSol(primal, set, stat, origprob, transprob, sol, insertpos, replace) || (*replace)) )
1178 return TRUE;
1179 }
1180
1181 return FALSE;
1182}
1183
1184/** check if we are willing to store the solution candidate for later checking */
1185static
1187 SCIP_PRIMAL* primal, /**< primal data */
1188 SCIP_SET* set, /**< global SCIP settings */
1189 SCIP_STAT* stat, /**< problem statistics data */
1190 SCIP_PROB* origprob, /**< original problem */
1191 SCIP_SOL* sol, /**< primal CIP solution */
1192 int* insertpos /**< pointer to store the insert position of that solution */
1193 )
1194{
1195 assert(SCIPsolIsOriginal(sol));
1196
1197 /* find insert position for the solution */
1198 (*insertpos) = primalSearchOrigSolPos(primal, sol);
1199
1200 if( !set->reopt_enable && (*insertpos) < set->limit_maxorigsol && !primalExistsOrigSol(primal, set, stat, origprob, sol, *insertpos) )
1201 return TRUE;
1202
1203 return FALSE;
1204}
1205
1206/** adds primal solution to solution storage by copying it */
1208 SCIP_PRIMAL* primal, /**< primal data */
1209 BMS_BLKMEM* blkmem, /**< block memory */
1210 SCIP_SET* set, /**< global SCIP settings */
1211 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1212 SCIP_STAT* stat, /**< problem statistics data */
1213 SCIP_PROB* origprob, /**< original problem */
1214 SCIP_PROB* transprob, /**< transformed problem after presolve */
1215 SCIP_TREE* tree, /**< branch and bound tree */
1216 SCIP_REOPT* reopt, /**< reoptimization data structure */
1217 SCIP_LP* lp, /**< current LP data */
1218 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1219 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1220 SCIP_SOL* sol, /**< primal CIP solution */
1221 SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1222 )
1223{
1224 SCIP_Bool replace;
1225 int insertpos;
1226
1227 assert(primal != NULL);
1228 assert(blkmem != NULL);
1229 assert(set != NULL);
1230 assert(messagehdlr != NULL);
1231 assert(stat != NULL);
1232 assert(origprob != NULL);
1233 assert(transprob != NULL);
1234 assert(tree != NULL);
1235 assert(lp != NULL);
1236 assert(eventqueue != NULL);
1237 assert(eventfilter != NULL);
1238 assert(sol != NULL);
1239 assert(stored != NULL);
1240
1241 insertpos = -1;
1242
1243 assert(!SCIPsolIsPartial(sol));
1244
1245 if( solOfInterest(primal, set, stat, origprob, transprob, sol, &insertpos, &replace) )
1246 {
1247 SCIP_SOL* solcopy;
1248#ifdef SCIP_MORE_DEBUG
1249 int i;
1250#endif
1251
1252 assert(insertpos >= 0 && insertpos < set->limit_maxsol);
1253
1254 /* create a copy of the solution */
1255 SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, primal, sol) );
1256
1257 /* insert copied solution into solution storage */
1258 SCIP_CALL( primalAddSol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1259 tree, reopt, lp, eventqueue, eventfilter, &solcopy, insertpos, replace) );
1260#ifdef SCIP_MORE_DEBUG
1261 for( i = 0; i < primal->nsols - 1; ++i )
1262 {
1263 assert(SCIPsetIsLE(set, SCIPsolGetObj(primal->sols[i], set, transprob, origprob), SCIPsolGetObj(primal->sols[i+1], set, transprob, origprob)));
1264 }
1265#endif
1266 *stored = TRUE;
1267 }
1268 else
1269 *stored = FALSE;
1270
1271 return SCIP_OKAY;
1272}
1273
1274/** adds primal solution to solution storage, frees the solution afterwards */
1276 SCIP_PRIMAL* primal, /**< primal data */
1277 BMS_BLKMEM* blkmem, /**< block memory */
1278 SCIP_SET* set, /**< global SCIP settings */
1279 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1280 SCIP_STAT* stat, /**< problem statistics data */
1281 SCIP_PROB* origprob, /**< original problem */
1282 SCIP_PROB* transprob, /**< transformed problem after presolve */
1283 SCIP_TREE* tree, /**< branch and bound tree */
1284 SCIP_REOPT* reopt, /**< reoptimization data structure */
1285 SCIP_LP* lp, /**< current LP data */
1286 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1287 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1288 SCIP_SOL** sol, /**< pointer to primal CIP solution; is cleared in function call */
1289 SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1290 )
1291{
1292 SCIP_Bool replace;
1293 int insertpos;
1294
1295 assert(primal != NULL);
1296 assert(transprob != NULL);
1297 assert(origprob != NULL);
1298 assert(sol != NULL);
1299 assert(*sol != NULL);
1300 assert(stored != NULL);
1301
1302 insertpos = -1;
1303
1304 if( solOfInterest(primal, set, stat, origprob, transprob, *sol, &insertpos, &replace) )
1305 {
1306 assert(insertpos >= 0 && insertpos < set->limit_maxsol);
1307
1308 /* insert solution into solution storage */
1309 SCIP_CALL( primalAddSol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1310 tree, reopt, lp, eventqueue, eventfilter, sol, insertpos, replace) );
1311
1312 /* clear the pointer, such that the user cannot access the solution anymore */
1313 *sol = NULL;
1314
1315 *stored = TRUE;
1316 }
1317 else
1318 {
1319 /* the solution is too bad -> free it immediately */
1320 SCIP_CALL( SCIPsolFree(sol, blkmem, primal) );
1321
1322 *stored = FALSE;
1323 }
1324 assert(*sol == NULL);
1325
1326 return SCIP_OKAY;
1327}
1328
1329/** adds primal solution to solution candidate storage of original problem space */
1331 SCIP_PRIMAL* primal, /**< primal data */
1332 BMS_BLKMEM* blkmem, /**< block memory */
1333 SCIP_SET* set, /**< global SCIP settings */
1334 SCIP_STAT* stat, /**< problem statistics data */
1335 SCIP_PROB* prob, /**< original problem data */
1336 SCIP_SOL* sol, /**< primal CIP solution; is cleared in function call */
1337 SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1338 )
1339{
1340 int insertpos;
1341
1342 assert(primal != NULL);
1343 assert(blkmem != NULL);
1344 assert(set != NULL);
1345 assert(stat != NULL);
1346 assert(sol != NULL);
1347 assert(SCIPsolIsOriginal(sol));
1348 assert(stored != NULL);
1349
1350 insertpos = -1;
1351
1352 if( SCIPsolIsPartial(sol) )
1353 {
1354 SCIP_SOL* solcopy;
1355
1356 /* create a copy of the solution */
1357 SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, primal, sol) );
1358
1359 SCIP_CALL( primalAddOrigPartialSol(primal, set, prob, solcopy) );
1360
1361 *stored = TRUE;
1362 }
1363 else if( origsolOfInterest(primal, set, stat, prob, sol, &insertpos) )
1364 {
1365 SCIP_SOL* solcopy;
1366
1367 assert(insertpos >= 0 && insertpos < set->limit_maxorigsol);
1368 assert(!set->reopt_enable);
1369
1370 /* create a copy of the solution */
1371 SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, primal, sol) );
1372
1373 /* insert solution into solution storage */
1374 SCIP_CALL( primalAddOrigSol(primal, blkmem, set, prob, solcopy, insertpos) );
1375
1376 *stored = TRUE;
1377 }
1378 else
1379 *stored = FALSE;
1380
1381 return SCIP_OKAY;
1382}
1383
1384/** adds primal solution to solution candidate storage of original problem space, frees the solution afterwards */
1386 SCIP_PRIMAL* primal, /**< primal data */
1387 BMS_BLKMEM* blkmem, /**< block memory */
1388 SCIP_SET* set, /**< global SCIP settings */
1389 SCIP_STAT* stat, /**< problem statistics data */
1390 SCIP_PROB* prob, /**< original problem data */
1391 SCIP_SOL** sol, /**< pointer to primal CIP solution; is cleared in function call */
1392 SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1393 )
1394{
1395 int insertpos;
1396
1397 assert(primal != NULL);
1398 assert(sol != NULL);
1399 assert(*sol != NULL);
1400 assert(SCIPsolIsOriginal(*sol));
1401 assert(stored != NULL);
1402
1403 insertpos = -1;
1404
1405 if( SCIPsolIsPartial(*sol) )
1406 {
1407 /* insert solution into solution storage */
1408 SCIP_CALL( primalAddOrigPartialSol(primal, set, prob, *sol) );
1409
1410 /* clear the pointer, such that the user cannot access the solution anymore */
1411 *sol = NULL;
1412
1413 *stored = TRUE;
1414 }
1415 else if( origsolOfInterest(primal, set, stat, prob, *sol, &insertpos) )
1416 {
1417 assert(insertpos >= 0 && insertpos < set->limit_maxorigsol);
1418 assert(!set->reopt_enable);
1419
1420 /* insert solution into solution storage */
1421 SCIP_CALL( primalAddOrigSol(primal, blkmem, set, prob, *sol, insertpos) );
1422
1423 /* clear the pointer, such that the user cannot access the solution anymore */
1424 *sol = NULL;
1425
1426 *stored = TRUE;
1427 }
1428 else
1429 {
1430 /* the solution is too bad -> free it immediately */
1431 SCIP_CALL( SCIPsolFree(sol, blkmem, primal) );
1432
1433 *stored = FALSE;
1434 }
1435 assert(*sol == NULL);
1436
1437 return SCIP_OKAY;
1438}
1439
1440/** links temporary solution of primal data to current solution */
1441static
1443 SCIP_PRIMAL* primal, /**< primal data */
1444 BMS_BLKMEM* blkmem, /**< block memory */
1445 SCIP_SET* set, /**< global SCIP settings */
1446 SCIP_STAT* stat, /**< problem statistics data */
1447 SCIP_PROB* prob, /**< transformed problem data */
1448 SCIP_TREE* tree, /**< branch and bound tree */
1449 SCIP_LP* lp, /**< current LP data */
1450 SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */
1451 )
1452{
1453 assert(primal != NULL);
1454
1455 if( primal->currentsol == NULL )
1456 {
1457 SCIP_CALL( SCIPsolCreateCurrentSol(&primal->currentsol, blkmem, set, stat, prob, primal, tree, lp, heur) );
1458 }
1459 else
1460 {
1461 SCIP_CALL( SCIPsolLinkCurrentSol(primal->currentsol, set, stat, prob, tree, lp) );
1462 SCIPsolSetHeur(primal->currentsol, heur);
1463 }
1464
1465 return SCIP_OKAY;
1466}
1467
1468/** adds current LP/pseudo solution to solution storage */
1470 SCIP_PRIMAL* primal, /**< primal data */
1471 BMS_BLKMEM* blkmem, /**< block memory */
1472 SCIP_SET* set, /**< global SCIP settings */
1473 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1474 SCIP_STAT* stat, /**< problem statistics data */
1475 SCIP_PROB* origprob, /**< original problem */
1476 SCIP_PROB* transprob, /**< transformed problem after presolve */
1477 SCIP_TREE* tree, /**< branch and bound tree */
1478 SCIP_REOPT* reopt, /**< reoptimization data structure */
1479 SCIP_LP* lp, /**< current LP data */
1480 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1481 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1482 SCIP_HEUR* heur, /**< heuristic that found the solution (or NULL if it's from the tree) */
1483 SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1484 )
1485{
1486 assert(primal != NULL);
1487
1488 /* link temporary solution to current solution */
1489 SCIP_CALL( primalLinkCurrentSol(primal, blkmem, set, stat, transprob, tree, lp, heur) );
1490
1491 /* add solution to solution storage */
1492 SCIP_CALL( SCIPprimalAddSol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1493 tree, reopt, lp, eventqueue, eventfilter, primal->currentsol, stored) );
1494
1495 return SCIP_OKAY;
1496}
1497
1498/** checks primal solution; if feasible, adds it to storage by copying it */
1500 SCIP_PRIMAL* primal, /**< primal data */
1501 BMS_BLKMEM* blkmem, /**< block memory */
1502 SCIP_SET* set, /**< global SCIP settings */
1503 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1504 SCIP_STAT* stat, /**< problem statistics data */
1505 SCIP_PROB* origprob, /**< original problem */
1506 SCIP_PROB* transprob, /**< transformed problem after presolve */
1507 SCIP_TREE* tree, /**< branch and bound tree */
1508 SCIP_REOPT* reopt, /**< reoptimization data structure */
1509 SCIP_LP* lp, /**< current LP data */
1510 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1511 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1512 SCIP_SOL* sol, /**< primal CIP solution */
1513 SCIP_Bool printreason, /**< Should all reasons of violations be printed? */
1514 SCIP_Bool completely, /**< Should all violations be checked? */
1515 SCIP_Bool checkbounds, /**< Should the bounds of the variables be checked? */
1516 SCIP_Bool checkintegrality, /**< Has integrality to be checked? */
1517 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
1518 SCIP_Bool* stored /**< stores whether given solution was feasible and good enough to keep */
1519 )
1520{
1521 SCIP_Bool feasible;
1522 SCIP_Bool replace;
1523 int insertpos;
1524
1525 assert(primal != NULL);
1526 assert(set != NULL);
1527 assert(transprob != NULL);
1528 assert(origprob != NULL);
1529 assert(tree != NULL);
1530 assert(sol != NULL);
1531 assert(stored != NULL);
1532
1533 /* if we want to solve exactly, the constraint handlers cannot rely on the LP's feasibility */
1534 checklprows = checklprows || set->misc_exactsolve;
1535
1536 insertpos = -1;
1537
1538 if( solOfInterest(primal, set, stat, origprob, transprob, sol, &insertpos, &replace) )
1539 {
1540 /* check solution for feasibility */
1541 SCIP_CALL( SCIPsolCheck(sol, set, messagehdlr, blkmem, stat, transprob, printreason, completely, checkbounds,
1542 checkintegrality, checklprows, &feasible) );
1543 }
1544 else
1545 feasible = FALSE;
1546
1547 if( feasible )
1548 {
1549 SCIP_SOL* solcopy;
1550
1551 assert(insertpos >= 0 && insertpos < set->limit_maxsol);
1552
1553 /* create a copy of the solution */
1554 SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, primal, sol) );
1555
1556 /* insert copied solution into solution storage */
1557 SCIP_CALL( primalAddSol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1558 tree, reopt, lp, eventqueue, eventfilter, &solcopy, insertpos, replace) );
1559
1560 *stored = TRUE;
1561 }
1562 else
1563 *stored = FALSE;
1564
1565 return SCIP_OKAY;
1566}
1567
1568/** checks primal solution; if feasible, adds it to storage; solution is freed afterwards */
1570 SCIP_PRIMAL* primal, /**< primal data */
1571 BMS_BLKMEM* blkmem, /**< block memory */
1572 SCIP_SET* set, /**< global SCIP settings */
1573 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1574 SCIP_STAT* stat, /**< problem statistics data */
1575 SCIP_PROB* origprob, /**< original problem */
1576 SCIP_PROB* transprob, /**< transformed problem after presolve */
1577 SCIP_TREE* tree, /**< branch and bound tree */
1578 SCIP_REOPT* reopt, /**< reoptimization data structure */
1579 SCIP_LP* lp, /**< current LP data */
1580 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1581 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1582 SCIP_SOL** sol, /**< pointer to primal CIP solution; is cleared in function call */
1583 SCIP_Bool printreason, /**< Should all the reasons of violations be printed? */
1584 SCIP_Bool completely, /**< Should all violations be checked? */
1585 SCIP_Bool checkbounds, /**< Should the bounds of the variables be checked? */
1586 SCIP_Bool checkintegrality, /**< Has integrality to be checked? */
1587 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
1588 SCIP_Bool* stored /**< stores whether solution was feasible and good enough to keep */
1589 )
1590{
1591 SCIP_Bool feasible;
1592 SCIP_Bool replace;
1593 int insertpos;
1594
1595 assert(primal != NULL);
1596 assert(transprob != NULL);
1597 assert(origprob != NULL);
1598 assert(tree != NULL);
1599 assert(sol != NULL);
1600 assert(*sol != NULL);
1601 assert(stored != NULL);
1602
1603 *stored = FALSE;
1604
1605 /* if we want to solve exactly, the constraint handlers cannot rely on the LP's feasibility */
1606 checklprows = checklprows || set->misc_exactsolve;
1607
1608 insertpos = -1;
1609
1610 if( solOfInterest(primal, set, stat, origprob, transprob, *sol, &insertpos, &replace) )
1611 {
1612 /* check solution for feasibility */
1613 SCIP_CALL( SCIPsolCheck(*sol, set, messagehdlr, blkmem, stat, transprob, printreason, completely, checkbounds,
1614 checkintegrality, checklprows, &feasible) );
1615 }
1616 else
1617 feasible = FALSE;
1618
1619 if( feasible )
1620 {
1621 assert(insertpos >= 0 && insertpos < set->limit_maxsol);
1622
1623 /* insert solution into solution storage */
1624 SCIP_CALL( primalAddSol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1625 tree, reopt, lp, eventqueue, eventfilter, sol, insertpos, replace) );
1626
1627 /* clear the pointer, such that the user cannot access the solution anymore */
1628 *sol = NULL;
1629 *stored = TRUE;
1630 }
1631 else
1632 {
1633 /* the solution is too bad or infeasible -> free it immediately */
1634 SCIP_CALL( SCIPsolFree(sol, blkmem, primal) );
1635 *stored = FALSE;
1636 }
1637 assert(*sol == NULL);
1638
1639 return SCIP_OKAY;
1640}
1641
1642/** checks current LP/pseudo solution; if feasible, adds it to storage */
1644 SCIP_PRIMAL* primal, /**< primal data */
1645 BMS_BLKMEM* blkmem, /**< block memory */
1646 SCIP_SET* set, /**< global SCIP settings */
1647 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1648 SCIP_STAT* stat, /**< problem statistics data */
1649 SCIP_PROB* origprob, /**< original problem */
1650 SCIP_PROB* transprob, /**< transformed problem after presolve */
1651 SCIP_TREE* tree, /**< branch and bound tree */
1652 SCIP_REOPT* reopt, /**< reoptimization data structure */
1653 SCIP_LP* lp, /**< current LP data */
1654 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1655 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1656 SCIP_HEUR* heur, /**< heuristic that found the solution (or NULL if it's from the tree) */
1657 SCIP_Bool printreason, /**< Should all reasons of violations be printed? */
1658 SCIP_Bool completely, /**< Should all violations be checked? */
1659 SCIP_Bool checkintegrality, /**< Has integrality to be checked? */
1660 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
1661 SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1662 )
1663{
1664 assert(primal != NULL);
1665
1666 /* link temporary solution to current solution */
1667 SCIP_CALL( primalLinkCurrentSol(primal, blkmem, set, stat, transprob, tree, lp, heur) );
1668
1669 /* add solution to solution storage */
1670 SCIP_CALL( SCIPprimalTrySol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1671 tree, reopt, lp, eventqueue, eventfilter, primal->currentsol,
1672 printreason, completely, FALSE, checkintegrality, checklprows, stored) );
1673
1674 return SCIP_OKAY;
1675}
1676
1677/** inserts solution into the global array of all existing primal solutions */
1679 SCIP_PRIMAL* primal, /**< primal data */
1680 SCIP_SET* set, /**< global SCIP settings */
1681 SCIP_SOL* sol /**< primal CIP solution */
1682 )
1683{
1684 assert(primal != NULL);
1685 assert(sol != NULL);
1686 assert(SCIPsolGetPrimalIndex(sol) == -1);
1687
1688 /* allocate memory for solution storage */
1689 SCIP_CALL( ensureExistingsolsSize(primal, set, primal->nexistingsols+1) );
1690
1691 /* append solution */
1693 primal->existingsols[primal->nexistingsols] = sol;
1694 primal->nexistingsols++;
1695
1696 return SCIP_OKAY;
1697}
1698
1699/** removes solution from the global array of all existing primal solutions */
1701 SCIP_PRIMAL* primal, /**< primal data */
1702 SCIP_SOL* sol /**< primal CIP solution */
1703 )
1704{
1705 int idx;
1706
1707 assert(primal != NULL);
1708 assert(sol != NULL);
1709
1710#ifndef NDEBUG
1711 for( idx = 0; idx < primal->nexistingsols; ++idx )
1712 {
1713 assert(idx == SCIPsolGetPrimalIndex(primal->existingsols[idx]));
1714 }
1715#endif
1716
1717 /* remove solution */
1718 idx = SCIPsolGetPrimalIndex(sol);
1719 assert(0 <= idx && idx < primal->nexistingsols);
1720 assert(sol == primal->existingsols[idx]);
1721 if( idx < primal->nexistingsols-1 )
1722 {
1723 primal->existingsols[idx] = primal->existingsols[primal->nexistingsols-1];
1724 SCIPsolSetPrimalIndex(primal->existingsols[idx], idx);
1725 }
1726 primal->nexistingsols--;
1727}
1728
1729/** updates all existing primal solutions after a change in a variable's objective value */
1731 SCIP_PRIMAL* primal, /**< primal data */
1732 SCIP_VAR* var, /**< problem variable */
1733 SCIP_Real oldobj, /**< old objective value */
1734 SCIP_Real newobj /**< new objective value */
1735 )
1736{
1737 int i;
1738
1739 assert(primal != NULL);
1740
1741 for( i = 0; i < primal->nexistingsols; ++i )
1742 {
1743 if( !SCIPsolIsOriginal(primal->existingsols[i]) )
1744 SCIPsolUpdateVarObj(primal->existingsols[i], var, oldobj, newobj);
1745 }
1746}
1747
1748/** retransforms all existing solutions to original problem space
1749 *
1750 * @note as a side effect, the objective value of the solutions can change (numerical errors)
1751 * so we update the objective cutoff value and upper bound accordingly
1752 */
1754 SCIP_PRIMAL* primal, /**< primal data */
1755 BMS_BLKMEM* blkmem, /**< block memory */
1756 SCIP_SET* set, /**< global SCIP settings */
1757 SCIP_STAT* stat, /**< problem statistics data */
1758 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1759 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1760 SCIP_PROB* origprob, /**< original problem */
1761 SCIP_PROB* transprob, /**< transformed problem */
1762 SCIP_TREE* tree, /**< branch and bound tree */
1763 SCIP_REOPT* reopt, /**< reoptimization data structure */
1764 SCIP_LP* lp /**< current LP data */
1765 )
1766{
1767 SCIP_Bool hasinfval;
1768 int i;
1769
1770 assert(primal != NULL);
1771
1772 for( i = 0; i < primal->nsols; ++i )
1773 {
1774 if( SCIPsolGetOrigin(primal->sols[i]) == SCIP_SOLORIGIN_ZERO )
1775 {
1776 SCIP_CALL( SCIPsolRetransform(primal->sols[i], set, stat, origprob, transprob, &hasinfval) );
1777 }
1778 }
1779
1780 sortPrimalSols(primal, set, origprob, transprob);
1781
1782 /* check if the global upper bound has to be updated
1783 * @todo we do not inform anybody about this change; if this leads to some
1784 * problem, a possible solution is to issue a BESTSOLFOUND event
1785 */
1786 if( primal->nsols > 0 )
1787 {
1788 SCIP_Real obj;
1789
1790 obj = SCIPsolGetObj(primal->sols[0], set, transprob, origprob);
1791 if( obj < primal->cutoffbound )
1792 {
1793 /* update the upper bound */
1794 SCIP_CALL( SCIPprimalSetUpperbound(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, tree, reopt, lp, obj) );
1795 }
1796 }
1797
1798 return SCIP_OKAY;
1799}
1800
1801/** tries to transform original solution to the transformed problem space */
1803 SCIP_PRIMAL* primal, /**< primal data */
1804 SCIP_SOL* sol, /**< primal solution */
1805 BMS_BLKMEM* blkmem, /**< block memory */
1806 SCIP_SET* set, /**< global SCIP settings */
1807 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1808 SCIP_STAT* stat, /**< problem statistics data */
1809 SCIP_PROB* origprob, /**< original problem */
1810 SCIP_PROB* transprob, /**< transformed problem after presolve */
1811 SCIP_TREE* tree, /**< branch and bound tree */
1812 SCIP_REOPT* reopt, /**< reoptimization data structure */
1813 SCIP_LP* lp, /**< current LP data */
1814 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1815 SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1816 SCIP_Real* solvals, /**< array for internal use to store solution values, or NULL;
1817 * if the method is called multiple times in a row, an array with size >=
1818 * number of active variables should be given for performance reasons */
1819 SCIP_Bool* solvalset, /**< array for internal use to store which solution values were set, or NULL;
1820 * if the method is called multiple times in a row, an array with size >=
1821 * number of active variables should be given for performance reasons */
1822 int solvalssize, /**< size of solvals and solvalset arrays, should be >= number of active
1823 * variables */
1824 SCIP_Bool* added /**< pointer to store whether the solution was added */
1825 )
1826{
1827 SCIP_VAR** origvars;
1828 SCIP_VAR** transvars;
1829 SCIP_VAR* var;
1830 SCIP_Real* localsolvals;
1831 SCIP_Bool* localsolvalset;
1832 SCIP_Real solval;
1833 SCIP_Real scalar;
1834 SCIP_Real constant;
1835 SCIP_Bool localarrays;
1836 SCIP_Bool feasible;
1837 int norigvars;
1838 int ntransvars;
1839 int nvarsset;
1840 int v;
1841
1842 assert(origprob != NULL);
1843 assert(transprob != NULL);
1844 assert(SCIPsolIsOriginal(sol));
1845 assert(solvalssize == 0 || solvals != NULL);
1846 assert(solvalssize == 0 || solvalset != NULL);
1847
1848 origvars = SCIPprobGetVars(origprob);
1849 norigvars = SCIPprobGetNVars(origprob);
1850 transvars = SCIPprobGetVars(transprob);
1851 ntransvars = SCIPprobGetNVars(transprob);
1852 assert(solvalssize == 0 || solvalssize >= ntransvars);
1853
1854 SCIPsetDebugMsg(set, "try to transfer original solution %p with objective %g into the transformed problem space\n",
1855 (void*)sol, SCIPsolGetOrigObj(sol));
1856
1857 /* if no solvals and solvalset arrays are given, allocate local ones, otherwise use the given ones */
1858 localarrays = (solvalssize == 0);
1859 if( localarrays )
1860 {
1861 SCIP_CALL( SCIPsetAllocBufferArray(set, &localsolvals, ntransvars) );
1862 SCIP_CALL( SCIPsetAllocBufferArray(set, &localsolvalset, ntransvars) );
1863 }
1864 else
1865 {
1866 localsolvals = solvals;
1867 localsolvalset = solvalset;
1868 }
1869
1870 BMSclearMemoryArray(localsolvalset, ntransvars);
1871 feasible = TRUE;
1872 (*added) = FALSE;
1873 nvarsset = 0;
1874
1875 /* for each original variable, get the corresponding active, fixed or multi-aggregated variable;
1876 * if it resolves to an active variable, we set its solution value or check whether an already stored solution value
1877 * is consistent; if it resolves to a fixed variable, we check that the fixing matches the original solution value;
1878 * multi-aggregated variables are skipped, because their value is defined by setting solution values for the active
1879 * variables, anyway
1880 */
1881 for( v = 0; v < norigvars && feasible; ++v )
1882 {
1883 var = origvars[v];
1884
1885 solval = SCIPsolGetVal(sol, set, stat, var);
1886
1887 /* get corresponding active, fixed, or multi-aggregated variable */
1888 scalar = 1.0;
1889 constant = 0.0;
1890 SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &constant) );
1893
1894 /* check whether the fixing corresponds to the solution value of the original variable */
1895 if( scalar == 0.0 )
1896 {
1897 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED ||
1898 (SCIPsetIsInfinity(set, constant) || SCIPsetIsInfinity(set, -constant)));
1899
1900 if( !SCIPsetIsEQ(set, solval, constant) )
1901 {
1902 SCIPsetDebugMsg(set, "original variable <%s> (solval=%g) resolves to fixed variable <%s> (original solval=%g)\n",
1903 SCIPvarGetName(origvars[v]), solval, SCIPvarGetName(var), constant);
1904 feasible = FALSE;
1905 }
1906 }
1907 else if( SCIPvarIsActive(var) )
1908 {
1909 /* if we already assigned a solution value to the transformed variable, check that it corresponds to the
1910 * value obtained from the currently regarded original variable
1911 */
1912 if( localsolvalset[SCIPvarGetProbindex(var)] )
1913 {
1914 if( !SCIPsetIsEQ(set, solval, scalar * localsolvals[SCIPvarGetProbindex(var)] + constant) )
1915 {
1916 SCIPsetDebugMsg(set, "original variable <%s> (solval=%g) resolves to active variable <%s> with assigned solval %g (original solval=%g)\n",
1917 SCIPvarGetName(origvars[v]), solval, SCIPvarGetName(var), localsolvals[SCIPvarGetProbindex(var)],
1918 scalar * localsolvals[SCIPvarGetProbindex(var)] + constant);
1919 feasible = FALSE;
1920 }
1921 }
1922 /* assign solution value to the transformed variable */
1923 else
1924 {
1925 assert(scalar != 0.0);
1926
1927 localsolvals[SCIPvarGetProbindex(var)] = (solval - constant) / scalar;
1928 localsolvalset[SCIPvarGetProbindex(var)] = TRUE;
1929 ++nvarsset;
1930 }
1931 }
1932#ifndef NDEBUG
1933 /* we do not have to handle multi-aggregated variables here, since by assigning values to all active variabes,
1934 * we implicitly assign values to the multi-aggregated variables, too
1935 */
1936 else
1938#endif
1939 }
1940
1941 /* if the solution values of fixed and active variables lead to no contradiction, construct solution and try it */
1942 if( feasible )
1943 {
1944 SCIP_SOL* transsol;
1945
1946 SCIP_CALL( SCIPsolCreate(&transsol, blkmem, set, stat, primal, tree, SCIPsolGetHeur(sol)) );
1947
1948 /* set solution values for variables to which we assigned a value */
1949 for( v = 0; v < ntransvars; ++v )
1950 {
1951 if( localsolvalset[v] )
1952 {
1953 SCIP_CALL( SCIPsolSetVal(transsol, set, stat, tree, transvars[v], localsolvals[v]) );
1954 }
1955 }
1956
1957 SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1958 tree, reopt, lp, eventqueue, eventfilter, &transsol, FALSE, FALSE, TRUE, TRUE, TRUE, added) );
1959
1960 SCIPsetDebugMsg(set, "solution transferred, %d/%d active variables set (stored=%u)\n", nvarsset, ntransvars, *added);
1961 }
1962 else
1963 (*added) = FALSE;
1964
1965 /* free local arrays, if needed */
1966 if( localarrays )
1967 {
1968 SCIPsetFreeBufferArray(set, &localsolvalset);
1969 SCIPsetFreeBufferArray(set, &localsolvals);
1970 }
1971
1972 return SCIP_OKAY;
1973}
1974
1975
1976/** is the updating of violations enabled for this problem? */
1978 SCIP_PRIMAL* primal /**< problem data */
1979 )
1980{
1981 assert(primal != NULL);
1982
1983 return primal->updateviolations;
1984}
1985
1986/** set whether the updating of violations is turned on */
1988 SCIP_PRIMAL* primal, /**< problem data */
1989 SCIP_Bool updateviolations /**< marks whether the updating of violations is turned on */
1990 )
1991{
1992 assert(primal != NULL);
1993
1994 primal->updateviolations = updateviolations;
1995}
#define SCIPdebugSolIsEnabled(scip)
Definition: debug.h:303
common defines and data types used in all packages of SCIP
#define NULL
Definition: def.h:262
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:238
#define SCIP_ALLOC(x)
Definition: def.h:380
#define SCIP_Real
Definition: def.h:172
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define SCIP_LONGINT_FORMAT
Definition: def.h:164
#define REALABS(x)
Definition: def.h:196
#define SCIP_CALL(x)
Definition: def.h:369
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:1354
SCIP_RETCODE SCIPeventProcess(SCIP_EVENT *event, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter)
Definition: event.c:1574
SCIP_RETCODE SCIPeventChgType(SCIP_EVENT *event, SCIP_EVENTTYPE eventtype)
Definition: event.c:1040
internal methods for managing events
SCIP_SOLORIGIN SCIPsolGetOrigin(SCIP_SOL *sol)
Definition: sol.c:2711
SCIP_Real SCIPsolGetOrigObj(SCIP_SOL *sol)
Definition: sol.c:2741
SCIP_Real SCIPsolGetTime(SCIP_SOL *sol)
Definition: sol.c:2764
SCIP_Longint SCIPsolGetNodenum(SCIP_SOL *sol)
Definition: sol.c:2784
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition: sol.c:2804
SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
Definition: sol.c:2721
int SCIPsolGetDepth(SCIP_SOL *sol)
Definition: sol.c:2794
SCIP_Bool SCIPsolIsPartial(SCIP_SOL *sol)
Definition: sol.c:2731
int SCIPsolGetRunnum(SCIP_SOL *sol)
Definition: sol.c:2774
void SCIPsolSetHeur(SCIP_SOL *sol, SCIP_HEUR *heur)
Definition: sol.c:2849
SCIP_Real SCIPgetDualbound(SCIP *scip)
SCIP_Real SCIPgetLowerbound(SCIP *scip)
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17766
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17556
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17786
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17437
SCIP_RETCODE SCIPlpSetCutoffbound(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_Real cutoffbound)
Definition: lp.c:10198
internal methods for 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:1469
void SCIPprimalSetUpdateViolations(SCIP_PRIMAL *primal, SCIP_Bool updateviolations)
Definition: primal.c:1987
SCIP_RETCODE SCIPprimalUpdateRay(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *primalray, BMS_BLKMEM *blkmem)
Definition: primal.c:584
void SCIPprimalSolFreed(SCIP_PRIMAL *primal, SCIP_SOL *sol)
Definition: primal.c:1700
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:613
static SCIP_Bool origsolOfInterest(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_SOL *sol, int *insertpos)
Definition: primal.c:1186
SCIP_RETCODE SCIPprimalSetUpperbound(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_Real upperbound)
Definition: primal.c:399
static int primalSearchSolPos(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_SOL *sol)
Definition: primal.c:929
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:1385
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:1643
static SCIP_RETCODE ensureExistingsolsSize(SCIP_PRIMAL *primal, SCIP_SET *set, int num)
Definition: primal.c:108
void SCIPprimalAddOrigObjoffset(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_Real addval)
Definition: primal.c:527
SCIP_RETCODE SCIPprimalFree(SCIP_PRIMAL **primal, BMS_BLKMEM *blkmem)
Definition: primal.c:160
static SCIP_Bool primalExistsOrigSol(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_SOL *sol, int insertpos)
Definition: primal.c:1096
static SCIP_RETCODE primalAddOrigSol(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_SOL *sol, int insertpos)
Definition: primal.c:846
SCIP_SOL * SCIPprimalGetRay(SCIP_PRIMAL *primal)
Definition: primal.c:574
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:1569
SCIP_Bool SCIPprimalUpdateViolations(SCIP_PRIMAL *primal)
Definition: primal.c:1977
SCIP_Bool SCIPprimalUpperboundIsSol(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_PROB *transprob, SCIP_PROB *origprob)
Definition: primal.c:561
static SCIP_RETCODE ensureSolsSize(SCIP_PRIMAL *primal, SCIP_SET *set, int num)
Definition: primal.c:60
static void sortPrimalSols(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_PROB *origprob, SCIP_PROB *transprob)
Definition: primal.c:230
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:1330
static SCIP_RETCODE primalSetCutoffbound(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_Real cutoffbound)
Definition: primal.c:257
void SCIPprimalUpdateVarObj(SCIP_PRIMAL *primal, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: primal.c:1730
SCIP_RETCODE SCIPprimalCreate(SCIP_PRIMAL **primal)
Definition: primal.c:130
SCIP_RETCODE SCIPprimalUpdateObjoffset(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition: primal.c:471
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:1442
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:1499
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:1802
SCIP_RETCODE SCIPprimalUpdateObjlimit(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition: primal.c:431
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:1275
static SCIP_RETCODE primalSetUpperbound(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_Real upperbound)
Definition: primal.c:344
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:1207
static int primalSearchOrigSolPos(SCIP_PRIMAL *primal, SCIP_SOL *sol)
Definition: primal.c:979
SCIP_RETCODE SCIPprimalSetCutoffbound(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_Real cutoffbound, SCIP_Bool useforobjlimit)
Definition: primal.c:290
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:1148
SCIP_RETCODE SCIPprimalSolCreated(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_SOL *sol)
Definition: primal.c:1678
SCIP_RETCODE SCIPprimalRetransformSolutions(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition: primal.c:1753
SCIP_RETCODE SCIPprimalClear(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem)
Definition: primal.c:179
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:1014
static SCIP_RETCODE ensurePartialsolsSize(SCIP_PRIMAL *primal, SCIP_SET *set, int num)
Definition: primal.c:83
static SCIP_RETCODE primalAddOrigPartialSol(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_PROB *prob, SCIP_SOL *sol)
Definition: primal.c:898
internal methods for collecting primal CIP solutions and primal informations
SCIP_Real SCIPprobGetObjlim(SCIP_PROB *prob, SCIP_SET *set)
Definition: prob.c:2370
SCIP_OBJSENSE SCIPprobGetObjsense(SCIP_PROB *prob)
Definition: prob.c:2518
void SCIPprobSetObjlim(SCIP_PROB *prob, SCIP_Real objlim)
Definition: prob.c:1505
SCIP_Bool SCIPprobIsObjIntegral(SCIP_PROB *prob)
Definition: prob.c:2346
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2401
SCIP_Real SCIPprobExternObjval(SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_SET *set, SCIP_Real objval)
Definition: prob.c:2157
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2446
SCIP_Real SCIPprobInternObjval(SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_SET *set, SCIP_Real objval)
Definition: prob.c:2179
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 querying solving statistics
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6293
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6775
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6663
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6641
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6257
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:6086
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6221
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:2952
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:6064
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6239
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6199
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6275
SCIP_Real SCIPsetCutoffbounddelta(SCIP_SET *set)
Definition: set.c:6164
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6685
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5764
internal methods for global SCIP settings
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1755
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1748
#define SCIPsetDebugMsg
Definition: set.h:1784
void SCIPsolUpdateVarObj(SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: sol.c:1588
void SCIPsolSetPrimalIndex(SCIP_SOL *sol, int primalindex)
Definition: sol.c:2824
int SCIPsolGetPrimalIndex(SCIP_SOL *sol)
Definition: sol.c:2814
SCIP_RETCODE SCIPsolLinkCurrentSol(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_LP *lp)
Definition: sol.c:988
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:1838
SCIP_RETCODE SCIPsolFree(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_PRIMAL *primal)
Definition: sol.c:801
SCIP_RETCODE SCIPsolRetransform(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_Bool *hasinfval)
Definition: sol.c:2059
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:703
SCIP_RETCODE SCIPsolTransform(SCIP_SOL *sol, SCIP_SOL **transsol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal)
Definition: sol.c:426
SCIP_RETCODE SCIPsolSetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_VAR *var, SCIP_Real val)
Definition: sol.c:1077
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1372
SCIP_RETCODE SCIPsolUnlink(SCIP_SOL *sol, SCIP_SET *set, SCIP_PROB *prob)
Definition: sol.c:1048
SCIP_Bool SCIPsolsAreEqual(SCIP_SOL *sol1, SCIP_SOL *sol2, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob)
Definition: sol.c:2221
SCIP_Real SCIPsolGetObj(SCIP_SOL *sol, SCIP_SET *set, SCIP_PROB *transprob, SCIP_PROB *origprob)
Definition: sol.c:1571
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:2286
void SCIPsolUpdateVarsum(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_Real weight)
Definition: sol.c:2031
SCIP_RETCODE SCIPsolCopy(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *primal, SCIP_SOL *sourcesol)
Definition: sol.c:362
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:288
void SCIPsolOrigAddObjval(SCIP_SOL *sol, SCIP_Real addval)
Definition: sol.c:2752
internal methods for storing primal CIP solutions
internal methods for problem statistics
SCIP_SOL * currentsol
Definition: struct_primal.h:60
int partialsolssize
Definition: struct_primal.h:64
int existingsolssize
Definition: struct_primal.h:67
SCIP_SOL ** partialsols
Definition: struct_primal.h:58
SCIP_SOL ** sols
Definition: struct_primal.h:57
SCIP_Longint nlimbestsolsfound
Definition: struct_primal.h:52
SCIP_Longint nbestsolsfound
Definition: struct_primal.h:51
SCIP_Bool updateviolations
Definition: struct_primal.h:70
SCIP_SOL * primalray
Definition: struct_primal.h:61
SCIP_Longint nsolsfound
Definition: struct_primal.h:48
SCIP_Longint nlimsolsfound
Definition: struct_primal.h:49
SCIP_Real cutoffbound
Definition: struct_primal.h:55
SCIP_SOL ** existingsols
Definition: struct_primal.h:59
SCIP_Real upperbound
Definition: struct_primal.h:54
SCIP_Longint nnodes
Definition: struct_stat.h:82
int firstprimaldepth
Definition: struct_stat.h:272
SCIP_VISUAL * visual
Definition: struct_stat.h:184
SCIP_Real firstprimaltime
Definition: struct_stat.h:134
int nrunsbeforefirst
Definition: struct_stat.h:271
SCIP_HEUR * firstprimalheur
Definition: struct_stat.h:185
SCIP_Longint nnodesbeforefirst
Definition: struct_stat.h:122
SCIP_Longint bestsolnode
Definition: struct_stat.h:113
SCIP_Real firstprimalbound
Definition: struct_stat.h:133
datastructures for managing events
Definition: heur_padm.c:135
SCIP_NODE * SCIPtreeGetCurrentNode(SCIP_TREE *tree)
Definition: tree.c:8506
int SCIPtreeGetCurrentDepth(SCIP_TREE *tree)
Definition: tree.c:8523
SCIP_RETCODE SCIPtreeCutoff(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real cutoffbound)
Definition: tree.c:5244
SCIP_Bool SCIPtreeInRepropagation(SCIP_TREE *tree)
Definition: tree.c:8496
internal methods for branch and bound tree
#define SCIP_EVENTTYPE_POORSOLFOUND
Definition: type_event.h:104
#define SCIP_EVENTTYPE_BESTSOLFOUND
Definition: type_event.h:105
@ SCIP_OBJSENSE_MINIMIZE
Definition: type_prob.h:48
@ 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:52
@ SCIP_VARSTATUS_MULTAGGR
Definition: type_var.h:54
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12665
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)