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-2015 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file primal.c
17  * @brief methods for collecting primal CIP solutions and primal informations
18  * @author Tobias Achterberg
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include <assert.h>
24 
25 #include "scip/def.h"
26 #include "scip/set.h"
27 #include "scip/stat.h"
28 #include "scip/visual.h"
29 #include "scip/event.h"
30 #include "scip/lp.h"
31 #include "scip/var.h"
32 #include "scip/prob.h"
33 #include "scip/sol.h"
34 #include "scip/primal.h"
35 #include "scip/tree.h"
36 #include "scip/reopt.h"
37 #include "scip/disp.h"
38 #include "scip/pub_message.h"
39 
40 
41 /*
42  * memory growing methods for dynamically allocated arrays
43  */
44 
45 /** ensures, that sols array can store at least num entries */
46 static
48  SCIP_PRIMAL* primal, /**< primal data */
49  SCIP_SET* set, /**< global SCIP settings */
50  int num /**< minimum number of entries to store */
51  )
52 {
53  assert(primal->nsols <= primal->solssize);
54 
55  if( num > primal->solssize )
56  {
57  int newsize;
58 
59  newsize = SCIPsetCalcMemGrowSize(set, num);
60  SCIP_ALLOC( BMSreallocMemoryArray(&primal->sols, newsize) );
61  primal->solssize = newsize;
62  }
63  assert(num <= primal->solssize);
64 
65  return SCIP_OKAY;
66 }
67 
68 /** ensures, that existingsols array can store at least num entries */
69 static
71  SCIP_PRIMAL* primal, /**< primal data */
72  SCIP_SET* set, /**< global SCIP settings */
73  int num /**< minimum number of entries to store */
74  )
75 {
76  assert(primal->nexistingsols <= primal->existingsolssize);
77 
78  if( num > primal->existingsolssize )
79  {
80  int newsize;
81 
82  newsize = SCIPsetCalcMemGrowSize(set, num);
83  SCIP_ALLOC( BMSreallocMemoryArray(&primal->existingsols, newsize) );
84  primal->existingsolssize = newsize;
85  }
86  assert(num <= primal->existingsolssize);
87 
88  return SCIP_OKAY;
89 }
90 
91 /** creates primal data */
93  SCIP_PRIMAL** primal /**< pointer to primal data */
94  )
95 {
96  assert(primal != NULL);
97 
98  SCIP_ALLOC( BMSallocMemory(primal) );
99  (*primal)->sols = NULL;
100  (*primal)->existingsols = NULL;
101  (*primal)->currentsol = NULL;
102  (*primal)->primalray = NULL;
103  (*primal)->solssize = 0;
104  (*primal)->nsols = 0;
105  (*primal)->existingsolssize = 0;
106  (*primal)->nexistingsols = 0;
107  (*primal)->nsolsfound = 0;
108  (*primal)->nlimsolsfound = 0;
109  (*primal)->nbestsolsfound = 0;
110  (*primal)->nlimbestsolsfound = 0;
111  (*primal)->upperbound = SCIP_INVALID;
112  (*primal)->cutoffbound = SCIP_INVALID;
113 
114  return SCIP_OKAY;
115 }
116 
117 /** frees primal data */
119  SCIP_PRIMAL** primal, /**< pointer to primal data */
120  BMS_BLKMEM* blkmem /**< block memory */
121  )
122 {
123  int s;
124 
125  assert(primal != NULL);
126  assert(*primal != NULL);
127 
128  /* free temporary solution for storing current solution */
129  if( (*primal)->currentsol != NULL )
130  {
131  SCIP_CALL( SCIPsolFree(&(*primal)->currentsol, blkmem, *primal) );
132  }
133 
134  /* free solution for storing primal ray */
135  if( (*primal)->primalray != NULL )
136  {
137  SCIP_CALL( SCIPsolFree(&(*primal)->primalray, blkmem, *primal) );
138  }
139 
140  /* free feasible primal CIP solutions */
141  for( s = 0; s < (*primal)->nsols; ++s )
142  {
143  SCIP_CALL( SCIPsolFree(&(*primal)->sols[s], blkmem, *primal) );
144  }
145  assert((*primal)->nexistingsols == 0);
146 
147  BMSfreeMemoryArrayNull(&(*primal)->sols);
148  BMSfreeMemoryArrayNull(&(*primal)->existingsols);
149  BMSfreeMemory(primal);
150 
151  return SCIP_OKAY;
152 }
153 
154 /** sets the cutoff bound in primal data and in LP solver */
155 static
157  SCIP_PRIMAL* primal, /**< primal data */
158  BMS_BLKMEM* blkmem, /**< block memory */
159  SCIP_SET* set, /**< global SCIP settings */
160  SCIP_STAT* stat, /**< problem statistics data */
161  SCIP_PROB* prob, /**< problem data */
162  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
163  SCIP_TREE* tree, /**< branch and bound tree */
164  SCIP_REOPT* reopt, /**< reoptimization data structure */
165  SCIP_LP* lp, /**< current LP data */
166  SCIP_Real cutoffbound /**< new cutoff bound */
167  )
168 {
169  assert(primal != NULL);
170  assert(cutoffbound <= SCIPsetInfinity(set));
171  assert(primal->upperbound == SCIP_INVALID || SCIPsetIsLE(set, cutoffbound, primal->upperbound)); /*lint !e777*/
172  assert(!SCIPtreeInRepropagation(tree));
173 
174  SCIPdebugMessage("changing cutoff bound from %g to %g\n", primal->cutoffbound, cutoffbound);
175 
176  primal->cutoffbound = MIN(cutoffbound, primal->upperbound); /* get rid of numerical issues */
177 
178  /* set cut off value in LP solver */
179  SCIP_CALL( SCIPlpSetCutoffbound(lp, set, prob, primal->cutoffbound) );
180 
181  /* cut off leaves of the tree */
182  SCIP_CALL( SCIPtreeCutoff(tree, reopt, blkmem, set, stat, eventqueue, lp, primal->cutoffbound) );
183 
184  return SCIP_OKAY;
185 }
186 
187 /** sets the cutoff bound in primal data and in LP solver */
189  SCIP_PRIMAL* primal, /**< primal data */
190  BMS_BLKMEM* blkmem, /**< block memory */
191  SCIP_SET* set, /**< global SCIP settings */
192  SCIP_STAT* stat, /**< problem statistics data */
193  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
194  SCIP_PROB* transprob, /**< transformed problem data */
195  SCIP_PROB* origprob, /**< original problem data */
196  SCIP_TREE* tree, /**< branch and bound tree */
197  SCIP_REOPT* reopt, /**< reoptimization data structure */
198  SCIP_LP* lp, /**< current LP data */
199  SCIP_Real cutoffbound, /**< new cutoff bound */
200  SCIP_Bool useforobjlimit /**< should the cutoff bound be used to update the objective limit, if
201  * better? */
202  )
203 {
204  assert(primal != NULL);
205  assert(cutoffbound <= SCIPsetInfinity(set));
206  assert(cutoffbound <= primal->upperbound);
207  assert(transprob != NULL);
208  assert(origprob != NULL);
209 
210  if( cutoffbound < primal->cutoffbound )
211  {
212  if( useforobjlimit )
213  {
214  SCIP_Real objval;
215 
216  objval = SCIPprobExternObjval(transprob, origprob, set, cutoffbound);
217 
218  if( objval < SCIPprobGetObjlim(origprob, set) )
219  {
220  SCIPdebugMessage("changing cutoff bound from %g to %g changes objective limit from %g to %g\n",
221  primal->cutoffbound, cutoffbound, SCIPprobGetObjlim(origprob, set), objval);
222  SCIPprobSetObjlim(origprob, objval);
223  SCIPprobSetObjlim(transprob, objval);
224  }
225  }
226 
227  /* update cutoff bound */
228  SCIP_CALL( primalSetCutoffbound(primal, blkmem, set, stat, transprob, eventqueue, tree, reopt, lp, cutoffbound) );
229  }
230  else if( cutoffbound > primal->cutoffbound )
231  {
232  SCIPerrorMessage("invalid increase in cutoff bound\n");
233  return SCIP_INVALIDDATA;
234  }
235 
236  return SCIP_OKAY;
237 }
238 
239 /** sets upper bound in primal data and in LP solver */
240 static
242  SCIP_PRIMAL* primal, /**< primal data */
243  BMS_BLKMEM* blkmem, /**< block memory */
244  SCIP_SET* set, /**< global SCIP settings */
245  SCIP_STAT* stat, /**< problem statistics data */
246  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
247  SCIP_PROB* prob, /**< transformed problem after presolve */
248  SCIP_TREE* tree, /**< branch and bound tree */
249  SCIP_REOPT* reopt, /**< reoptimization data structure */
250  SCIP_LP* lp, /**< current LP data */
251  SCIP_Real upperbound /**< new upper bound */
252  )
253 {
254  SCIP_Real cutoffbound;
255 
256  assert(primal != NULL);
257  assert(stat != NULL);
258  assert(upperbound <= SCIPsetInfinity(set));
259  assert(upperbound <= primal->upperbound || stat->nnodes == 0);
260 
261  SCIPdebugMessage("changing upper bound from %g to %g\n", primal->upperbound, upperbound);
262 
263  primal->upperbound = upperbound;
264 
265  /* if objective value is always integral, the cutoff bound can be reduced to nearly the previous integer number */
266  if( SCIPprobIsObjIntegral(prob) && !SCIPsetIsInfinity(set, upperbound) )
267  {
268  SCIP_Real delta;
269 
270  delta = SCIPsetCutoffbounddelta(set);
271 
272  cutoffbound = SCIPsetFeasCeil(set, upperbound) - (1.0 - delta);
273  cutoffbound = MIN(cutoffbound, upperbound); /* SCIPsetFeasCeil() can increase bound by almost 1.0 due to numerics
274  * and very large upperbound value */
275  }
276  else
277  cutoffbound = upperbound;
278 
279  /* update cutoff bound */
280  if( cutoffbound < primal->cutoffbound )
281  {
282  SCIP_CALL( primalSetCutoffbound(primal, blkmem, set, stat, prob, eventqueue, tree, reopt, lp, cutoffbound) );
283  }
284 
285  /* update upper bound in visualization output */
286  if( SCIPtreeGetCurrentDepth(tree) >= 0 )
287  {
288  SCIPvisualUpperbound(stat->visual, set, stat, primal->upperbound);
289  }
290 
291  return SCIP_OKAY;
292 }
293 
294 /** sets upper bound in primal data and in LP solver */
296  SCIP_PRIMAL* primal, /**< primal data */
297  BMS_BLKMEM* blkmem, /**< block memory */
298  SCIP_SET* set, /**< global SCIP settings */
299  SCIP_STAT* stat, /**< problem statistics data */
300  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
301  SCIP_PROB* prob, /**< transformed problem after presolve */
302  SCIP_TREE* tree, /**< branch and bound tree */
303  SCIP_REOPT* reopt, /**< reoptimization data structure */
304  SCIP_LP* lp, /**< current LP data */
305  SCIP_Real upperbound /**< new upper bound */
306  )
307 {
308  assert(primal != NULL);
309  assert(upperbound <= SCIPsetInfinity(set));
310 
311  if( upperbound < primal->upperbound )
312  {
313  /* update primal bound */
314  SCIP_CALL( primalSetUpperbound(primal, blkmem, set, stat, eventqueue, prob, tree, reopt, lp, upperbound) );
315  }
316  else if( upperbound > primal->upperbound )
317  {
318  SCIPerrorMessage("invalid increase in upper bound\n");
319  return SCIP_INVALIDDATA;
320  }
321 
322  return SCIP_OKAY;
323 }
324 
325 /** updates upper bound and cutoff bound in primal data after a tightening of the problem's objective limit */
327  SCIP_PRIMAL* primal, /**< primal data */
328  BMS_BLKMEM* blkmem, /**< block memory */
329  SCIP_SET* set, /**< global SCIP settings */
330  SCIP_STAT* stat, /**< problem statistics data */
331  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
332  SCIP_PROB* transprob, /**< tranformed problem data */
333  SCIP_PROB* origprob, /**< original problem data */
334  SCIP_TREE* tree, /**< branch and bound tree */
335  SCIP_REOPT* reopt, /**< reoptimization data structure */
336  SCIP_LP* lp /**< current LP data */
337  )
338 {
339  SCIP_Real objlimit;
340  SCIP_Real inf;
341 
342  assert(primal != NULL);
343 
344  /* get internal objective limit */
345  objlimit = SCIPprobInternObjval(transprob, origprob, set, SCIPprobGetObjlim(origprob, set));
346  inf = SCIPsetInfinity(set);
347  objlimit = MIN(objlimit, inf);
348 
349  /* update the cutoff bound */
350  if( objlimit < primal->cutoffbound )
351  {
352  SCIP_CALL( primalSetCutoffbound(primal, blkmem, set, stat, transprob, eventqueue, tree, reopt, lp, objlimit) );
353  }
354 
355  /* set new upper bound (and decrease cutoff bound, if objective value is always integral) */
356  if( objlimit < primal->upperbound )
357  {
358  SCIP_CALL( primalSetUpperbound(primal, blkmem, set, stat, eventqueue, transprob, tree, reopt, lp, objlimit) );
359  }
360 
361  return SCIP_OKAY;
362 }
363 
364 /** recalculates upper bound and cutoff bound in primal data after a change of the problem's objective offset */
366  SCIP_PRIMAL* primal, /**< primal data */
367  BMS_BLKMEM* blkmem, /**< block memory */
368  SCIP_SET* set, /**< global SCIP settings */
369  SCIP_STAT* stat, /**< problem statistics data */
370  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
371  SCIP_PROB* transprob, /**< tranformed problem data */
372  SCIP_PROB* origprob, /**< original problem data */
373  SCIP_TREE* tree, /**< branch and bound tree */
374  SCIP_REOPT* reopt, /**< reoptimization data structure */
375  SCIP_LP* lp /**< current LP data */
376  )
377 {
378  SCIP_SOL* sol;
379  SCIP_Real upperbound;
380  SCIP_Real objval;
381  SCIP_Real inf;
382  int i;
383  int j;
384 
385  assert(primal != NULL);
387 
388  /* recalculate internal objective limit */
389  upperbound = SCIPprobInternObjval(transprob, origprob, set, SCIPprobGetObjlim(origprob, set));
390  inf = SCIPsetInfinity(set);
391  upperbound = MIN(upperbound, inf);
392 
393  /* resort current primal solutions */
394  for( i = 1; i < primal->nsols; ++i )
395  {
396  sol = primal->sols[i];
397  objval = SCIPsolGetObj(sol, set, transprob, origprob);
398  for( j = i; j > 0 && objval < SCIPsolGetObj(primal->sols[j-1], set, transprob, origprob); --j )
399  primal->sols[j] = primal->sols[j-1];
400  primal->sols[j] = sol;
401  }
402 
403  /* compare objective limit to currently best solution */
404  if( primal->nsols > 0 )
405  {
406  SCIP_Real obj;
407 
408  assert(SCIPsolIsOriginal(primal->sols[0]));
409  obj = SCIPsolGetObj(primal->sols[0], set, transprob, origprob);
410 
411  upperbound = MIN(upperbound, obj);
412  }
413 
414  /* invalidate old upper bound */
415  SCIP_CALL( primalSetUpperbound(primal, blkmem, set, stat, eventqueue, transprob, tree, reopt, lp, SCIPsetInfinity(set)) );
416 
417  /* reset the cutoff bound
418  *
419  * @note we might need to relax the bound since in presolving the objective correction of an
420  * aggregation is still in progress
421  */
422  SCIP_CALL( primalSetCutoffbound(primal, blkmem, set, stat, transprob, eventqueue, tree, reopt, lp, upperbound) );
423 
424  /* set new upper bound (and decrease cutoff bound, if objective value is always integral) */
425  SCIP_CALL( primalSetUpperbound(primal, blkmem, set, stat, eventqueue, transprob, tree, reopt, lp, upperbound) );
426 
427  return SCIP_OKAY;
428 }
429 
430 /** adds additional objective offset in original space to all existing solution (in original space) */
432  SCIP_PRIMAL* primal, /**< primal data */
433  SCIP_SET* set, /**< global SCIP settings */
434  SCIP_Real addval /**< additional objective offset in original space */
435  )
436 {
437  int i;
438 
439  assert(primal != NULL);
440  assert(set != NULL);
441  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM);
442 
443 #ifndef NDEBUG
444  assert(primal->nsols == 0 || SCIPsolGetOrigin(primal->sols[0]) == SCIP_SOLORIGIN_ORIGINAL);
445 
446  /* check current order of primal solutions */
447  for( i = 1; i < primal->nsols; ++i )
448  {
449  assert(SCIPsolGetOrigin(primal->sols[i]) == SCIP_SOLORIGIN_ORIGINAL);
450  assert(SCIPsetIsLE(set, SCIPsolGetOrigObj(primal->sols[i-1]), SCIPsolGetOrigObj(primal->sols[i])));
451  }
452 #endif
453 
454  /* check current order of primal solutions */
455  for( i = 0; i < primal->nexistingsols; ++i )
456  {
457  assert(primal->existingsols[i] != NULL);
458  SCIPsolOrigAddObjval(primal->existingsols[i], addval);
459  }
460 }
461 
462 /** returns whether the current primal bound is justified with a feasible primal solution; if not, the primal bound
463  * was set from the user as objective limit
464  */
466  SCIP_PRIMAL* primal, /**< primal data */
467  SCIP_SET* set, /**< global SCIP settings */
468  SCIP_PROB* transprob, /**< tranformed problem data */
469  SCIP_PROB* origprob /**< original problem data */
470  )
471 {
472  assert(primal != NULL);
473 
474  return (primal->nsols > 0 && SCIPsetIsEQ(set, primal->upperbound, SCIPsolGetObj(primal->sols[0], set, transprob, origprob)));
475 }
476 
477 /** adds primal solution to solution storage at given position */
478 static
480  SCIP_PRIMAL* primal, /**< primal data */
481  BMS_BLKMEM* blkmem, /**< block memory */
482  SCIP_SET* set, /**< global SCIP settings */
483  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
484  SCIP_STAT* stat, /**< problem statistics data */
485  SCIP_PROB* origprob, /**< original problem */
486  SCIP_PROB* transprob, /**< transformed problem after presolve */
487  SCIP_TREE* tree, /**< branch and bound tree */
488  SCIP_REOPT* reopt, /**< reoptimization data structure */
489  SCIP_LP* lp, /**< current LP data */
490  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
491  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
492  SCIP_SOL** solptr, /**< pointer to primal CIP solution */
493  int insertpos, /**< position in solution storage to add solution to */
494  SCIP_Bool replace /**< should the solution at insertpos be replaced by the new solution? */
495  )
496 {
497  SCIP_SOL* sol;
498  SCIP_EVENT event;
499  SCIP_Real obj;
500  int pos;
501 
502  assert(primal != NULL);
503  assert(set != NULL);
504  assert(solptr != NULL);
505  assert(stat != NULL);
506  assert(transprob != NULL);
507  assert(origprob != NULL);
508  assert(0 <= insertpos && insertpos < set->limit_maxsol);
509  assert(tree == NULL || !SCIPtreeInRepropagation(tree));
510 
511  sol = *solptr;
512  assert(sol != NULL);
513  obj = SCIPsolGetObj(sol, set, transprob, origprob);
514 
515  SCIPdebugMessage("insert primal solution %p with obj %g at position %d (replace=%u):\n",
516  (void*)sol, obj, insertpos, replace);
517 
518  SCIPdebug( SCIP_CALL( SCIPsolPrint(sol, set, messagehdlr, stat, transprob, NULL, NULL, FALSE) ) );
519 
520 #if 0 /* this is not a valid debug check, but can be used to track down numerical troubles */
521 #ifndef NDEBUG
522  /* check solution again completely
523  * it fail for different reasons:
524  * - in the LP solver, the feasibility tolerance is a relative measure against the row's norm
525  * - in SCIP, the feasibility tolerance is a relative measure against the row's rhs/lhs
526  * - the rhs/lhs of a row might drastically change during presolving when variables are fixed or (multi-)aggregated
527  */
528  if( !SCIPsolIsOriginal(sol) )
529  {
530  SCIP_Bool feasible;
531 
532  SCIP_CALL( SCIPsolCheck(sol, set, messagehdlr, blkmem, stat, transprob, TRUE, TRUE, TRUE, TRUE, &feasible) );
533 
534  if( !feasible )
535  {
536  SCIPerrorMessage("infeasible solution accepted:\n");
537  SCIP_CALL( SCIPsolPrint(sol, set, messagehdlr, stat, origprob, transprob, NULL, FALSE) );
538  }
539  assert(feasible);
540  }
541 #endif
542 #endif
543 
544  /* completely fill the solution's own value array to unlink it from the LP or pseudo solution */
545  SCIP_CALL( SCIPsolUnlink(sol, set, transprob) );
546 
547  /* allocate memory for solution storage */
548  SCIP_CALL( ensureSolsSize(primal, set, set->limit_maxsol) );
549 
550  /* if set->limit_maxsol was decreased in the meantime, free all solutions exceeding the limit */
551  for( pos = set->limit_maxsol; pos < primal->nsols; ++pos )
552  {
553  SCIP_CALL( SCIPsolFree(&primal->sols[pos], blkmem, primal) );
554  }
555  primal->nsols = MIN(primal->nsols, set->limit_maxsol);
556 
557  /* if the solution should replace an existing one, free this solution, otherwise,
558  * free the last solution if the solution storage is full;
559  */
560  if( replace )
561  {
562  SCIP_CALL( SCIPsolTransform(primal->sols[insertpos], solptr, blkmem, set, primal) );
563  sol = primal->sols[insertpos];
564  }
565  else
566  {
567  if( primal->nsols == set->limit_maxsol )
568  {
569  SCIP_CALL( SCIPsolFree(&primal->sols[set->limit_maxsol - 1], blkmem, primal) );
570  }
571  else
572  {
573  primal->nsols = primal->nsols + 1;
574  assert(primal->nsols <= set->limit_maxsol);
575  }
576 
577  /* move all solutions with worse objective value than the new solution */
578  for( pos = primal->nsols-1; pos > insertpos; --pos )
579  primal->sols[pos] = primal->sols[pos-1];
580 
581  /* insert solution at correct position */
582  assert(0 <= insertpos && insertpos < primal->nsols);
583  primal->sols[insertpos] = sol;
584  primal->nsolsfound++;
585 
586  /* check if solution is better than objective limit */
587  if( SCIPsetIsFeasLE(set, obj, SCIPprobInternObjval(transprob, origprob, set, SCIPprobGetObjlim(origprob, set))) )
588  primal->nlimsolsfound++;
589  }
590 
591  /* if its the first primal solution, store the relevant statistics */
592  if( primal->nsolsfound == 1 )
593  {
594  SCIP_Real primalsolval;
595 
597  stat->nrunsbeforefirst = SCIPsolGetRunnum(sol);
598  stat->firstprimalheur = SCIPsolGetHeur(sol);
599  stat->firstprimaltime = SCIPsolGetTime(sol);
600  stat->firstprimaldepth = SCIPsolGetDepth(sol);
601 
602  primalsolval = obj;
603  stat->firstprimalbound = SCIPprobExternObjval(transprob, origprob, set, primalsolval);
604 
605  SCIPdebugMessage("First Solution stored in problem specific statistics.\n");
606  SCIPdebugMessage("-> %" SCIP_LONGINT_FORMAT " nodes, %d runs, %.2g time, %d depth, %.15g objective\n", stat->nnodesbeforefirst, stat->nrunsbeforefirst,
608  }
609 
610  SCIPdebugMessage(" -> stored at position %d of %d solutions, found %" SCIP_LONGINT_FORMAT " solutions\n",
611  insertpos, primal->nsols, primal->nsolsfound);
612 
613  /* update the solution value sums in variables */
614  if( !SCIPsolIsOriginal(sol) )
615  {
616  SCIPsolUpdateVarsum(sol, set, stat, transprob,
617  (SCIP_Real)(primal->nsols - insertpos)/(SCIP_Real)(2.0*primal->nsols - 1.0));
618  }
619 
620  /* change color of node in visualization output */
621  SCIPvisualFoundSolution(stat->visual, set, stat, SCIPtreeGetCurrentNode(tree), insertpos == 0 ? TRUE : FALSE, sol);
622 
623  /* check, if the global upper bound has to be updated */
624  if( obj < primal->upperbound )
625  {
626  /* update the upper bound */
627  SCIP_CALL( SCIPprimalSetUpperbound(primal, blkmem, set, stat, eventqueue, transprob, tree, reopt, lp, obj) );
628 
629  /* issue BESTSOLFOUND event */
631  primal->nbestsolsfound++;
632  stat->bestsolnode = stat->nnodes;
633  }
634  else
635  {
636  /* issue POORSOLFOUND event */
638  }
639  SCIP_CALL( SCIPeventChgSol(&event, sol) );
640  SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, eventfilter) );
641 
642  /* display node information line */
643  if( insertpos == 0 && !replace && set->stage >= SCIP_STAGE_SOLVING )
644  {
645  SCIP_CALL( SCIPdispPrintLine(set, messagehdlr, stat, NULL, TRUE, TRUE) );
646  }
647 
648  /* if an original solution was added during solving, try to transfer it to the transformed space */
650  {
651  SCIP_Bool added;
652 
653  SCIP_CALL( SCIPprimalTransformSol(primal, sol, blkmem, set, messagehdlr, stat, origprob, transprob, tree, reopt,
654  lp, eventqueue, eventfilter, NULL, NULL, 0, &added) );
655 
656  SCIPdebugMessage("original solution %p was successfully transferred to the transformed problem space\n",
657  (void*)sol);
658 
659  }
660 
661  return SCIP_OKAY;
662 }
663 
664 /** adds primal solution to solution storage at given position */
665 static
667  SCIP_PRIMAL* primal, /**< primal data */
668  BMS_BLKMEM* blkmem, /**< block memory */
669  SCIP_SET* set, /**< global SCIP settings */
670  SCIP_PROB* prob, /**< original problem data */
671  SCIP_SOL* sol, /**< primal CIP solution */
672  int insertpos /**< position in solution storage to add solution to */
673  )
674 {
675  int pos;
676 
677  assert(primal != NULL);
678  assert(set != NULL);
679  assert(prob != NULL);
680  assert(sol != NULL);
681  assert(0 <= insertpos && insertpos < set->limit_maxorigsol);
682 
683  SCIPdebugMessage("insert primal solution candidate %p with obj %g at position %d:\n", (void*)sol, SCIPsolGetOrigObj(sol), insertpos);
684 
685  /* allocate memory for solution storage */
686  SCIP_CALL( ensureSolsSize(primal, set, set->limit_maxorigsol) );
687 
688  /* if the solution storage is full, free the last solution(s)
689  * more than one solution may be freed, if set->limit_maxorigsol was decreased in the meantime
690  */
691  for( pos = set->limit_maxorigsol-1; pos < primal->nsols; ++pos )
692  {
693  SCIP_CALL( SCIPsolFree(&primal->sols[pos], blkmem, primal) );
694  }
695 
696  /* insert solution at correct position */
697  primal->nsols = MIN(primal->nsols+1, set->limit_maxorigsol);
698  for( pos = primal->nsols-1; pos > insertpos; --pos )
699  primal->sols[pos] = primal->sols[pos-1];
700 
701  assert(0 <= insertpos && insertpos < primal->nsols);
702  primal->sols[insertpos] = sol;
703  primal->nsolsfound++;
704 
705  /* check if solution is better than objective limit */
706  if( SCIPsetIsFeasLE(set, SCIPsolGetOrigObj(sol), SCIPprobGetObjlim(prob, set)) )
707  primal->nlimsolsfound++;
708 
709  SCIPdebugMessage(" -> stored at position %d of %d solutions, found %" SCIP_LONGINT_FORMAT " solutions\n",
710  insertpos, primal->nsols, primal->nsolsfound);
711 
712  return SCIP_OKAY;
713 }
714 
715 /** uses binary search to find position in solution storage */
716 static
718  SCIP_PRIMAL* primal, /**< primal data */
719  SCIP_SET* set, /**< global SCIP settings */
720  SCIP_PROB* transprob, /**< tranformed problem data */
721  SCIP_PROB* origprob, /**< original problem data */
722  SCIP_SOL* sol /**< primal solution to search position for */
723  )
724 {
725  SCIP_SOL** sols;
726  SCIP_Real obj;
727  SCIP_Real middleobj;
728  int left;
729  int right;
730  int middle;
731 
732  assert(primal != NULL);
733 
734  obj = SCIPsolGetObj(sol, set, transprob, origprob);
735  sols = primal->sols;
736 
737  left = -1;
738  right = primal->nsols;
739  while( left < right-1 )
740  {
741  middle = (left+right)/2;
742  assert(left < middle && middle < right);
743  assert(0 <= middle && middle < primal->nsols);
744 
745  middleobj = SCIPsolGetObj(sols[middle], set, transprob, origprob);
746 
747  if( obj < middleobj )
748  right = middle;
749  else
750  left = middle;
751  }
752  assert(left == right-1);
753 
754  /* prefer solutions that live in the transformed space */
755  if( !SCIPsolIsOriginal(sol) )
756  {
757  while( right > 0 && SCIPsolIsOriginal(sols[right-1])
758  && SCIPsetIsEQ(set, SCIPsolGetObj(sols[right-1], set, transprob, origprob), obj) )
759  --right;
760  }
761 
762  return right;
763 }
764 
765 /** uses binary search to find position in solution storage */
766 static
768  SCIP_PRIMAL* primal, /**< primal data */
769  SCIP_SOL* sol /**< primal solution to search position for */
770  )
771 {
772  SCIP_Real obj;
773  SCIP_Real middleobj;
774  int left;
775  int right;
776  int middle;
777 
778  assert(primal != NULL);
779 
780  obj = SCIPsolGetOrigObj(sol);
781 
782  left = -1;
783  right = primal->nsols;
784  while( left < right-1 )
785  {
786  middle = (left+right)/2;
787  assert(left < middle && middle < right);
788  assert(0 <= middle && middle < primal->nsols);
789  middleobj = SCIPsolGetOrigObj(primal->sols[middle]);
790  if( obj < middleobj )
791  right = middle;
792  else
793  left = middle;
794  }
795  assert(left == right-1);
796 
797  return right;
798 }
799 
800 /** returns whether the given primal solution is already existent in the solution storage */
801 static
803  SCIP_PRIMAL* primal, /**< primal data */
804  SCIP_SET* set, /**< global SCIP settings */
805  SCIP_STAT* stat, /**< problem statistics data */
806  SCIP_PROB* origprob, /**< original problem */
807  SCIP_PROB* transprob, /**< transformed problem after presolve */
808  SCIP_SOL* sol, /**< primal solution to search position for */
809  int* insertpos, /**< pointer to insertion position returned by primalSearchSolPos(); the
810  * position might be changed if an existing solution should be replaced */
811  SCIP_Bool* replace /**< pointer to store whether the solution at insertpos should be replaced */
812  )
813 {
814  SCIP_Real obj;
815  int i;
816 
817  assert(primal != NULL);
818  assert(insertpos != NULL);
819  assert(replace != NULL);
820  assert(0 <= (*insertpos) && (*insertpos) <= primal->nsols);
821 
822  obj = SCIPsolGetObj(sol, set, transprob, origprob);
823 
824  assert(primal->sols != NULL || primal->nsols == 0);
825  assert(primal->sols != NULL || (*insertpos) == 0);
826 
827  /* search in the better solutions */
828  for( i = (*insertpos)-1; i >= 0; --i )
829  {
830  SCIP_Real solobj;
831 
832  solobj = SCIPsolGetObj(primal->sols[i], set, transprob, origprob);
833 
834  /* due to transferring the objective value of transformed solutions to the original space, small numerical errors might occur
835  * which can lead to SCIPsetIsLE() failing in case of high absolute numbers
836  */
837  assert(SCIPsetIsLE(set, solobj, obj) || (REALABS(obj) > 1e+13 * SCIPsetEpsilon(set) && SCIPsetIsFeasLE(set, solobj, obj)));
838 
839  if( SCIPsetIsLT(set, solobj, obj) )
840  break;
841 
842  if( SCIPsolsAreEqual(sol, primal->sols[i], set, stat, origprob, transprob) )
843  {
844  if( SCIPsolIsOriginal(primal->sols[i]) && !SCIPsolIsOriginal(sol) )
845  {
846  (*insertpos) = i;
847  (*replace) = TRUE;
848  }
849  return TRUE;
850  }
851  }
852 
853  /* search in the worse solutions */
854  for( i = (*insertpos); i < primal->nsols; ++i )
855  {
856  SCIP_Real solobj;
857 
858  solobj = SCIPsolGetObj(primal->sols[i], set, transprob, origprob);
859 
860  /* due to transferring the objective value of transformed solutions to the original space, small numerical errors might occur
861  * which can lead to SCIPsetIsLE() failing in case of high absolute numbers
862  */
863  assert( SCIPsetIsGE(set, solobj, obj) || (REALABS(obj) > 1e+13 * SCIPsetEpsilon(set) && SCIPsetIsFeasGE(set, solobj, obj)));
864 
865  if( SCIPsetIsGT(set, solobj, obj) )
866  break;
867 
868  if( SCIPsolsAreEqual(sol, primal->sols[i], set, stat, origprob, transprob) )
869  {
870  if( SCIPsolIsOriginal(primal->sols[i]) && !SCIPsolIsOriginal(sol) )
871  {
872  (*insertpos) = i;
873  (*replace) = TRUE;
874  }
875  return TRUE;
876  }
877  }
878 
879  return FALSE;
880 }
881 
882 /** returns whether the given primal solution is already existent in the original solution candidate storage */
883 static
885  SCIP_PRIMAL* primal, /**< primal data */
886  SCIP_SET* set, /**< global SCIP settings */
887  SCIP_STAT* stat, /**< problem statistics data */
888  SCIP_PROB* prob, /**< original problem */
889  SCIP_SOL* sol, /**< primal solution to search position for */
890  int insertpos /**< insertion position returned by primalSearchOrigSolPos() */
891  )
892 {
893  SCIP_Real obj;
894  int i;
895 
896  assert(primal != NULL);
897  assert(0 <= insertpos && insertpos <= primal->nsols);
898 
899  obj = SCIPsolGetOrigObj(sol);
900 
901  /* search in the better solutions */
902  for( i = insertpos-1; i >= 0; --i )
903  {
904  SCIP_Real solobj;
905 
906  solobj = SCIPsolGetOrigObj(primal->sols[i]);
907  assert( SCIPsetIsLE(set, solobj, obj) );
908 
909  if( SCIPsetIsLT(set, solobj, obj) )
910  break;
911 
912  if( SCIPsolsAreEqual(sol, primal->sols[i], set, stat, prob, NULL) )
913  return TRUE;
914  }
915 
916  /* search in the worse solutions */
917  for( i = insertpos; i < primal->nsols; ++i )
918  {
919  SCIP_Real solobj;
920 
921  solobj = SCIPsolGetOrigObj(primal->sols[i]);
922  assert( SCIPsetIsGE(set, solobj, obj) );
923 
924  if( SCIPsetIsGT(set, solobj, obj) )
925  break;
926 
927  if( SCIPsolsAreEqual(sol, primal->sols[i], set, stat, prob, NULL) )
928  return TRUE;
929  }
930 
931  return FALSE;
932 }
933 
934 /** check if we are willing to check the solution for feasibility */
935 static
937  SCIP_PRIMAL* primal, /**< primal data */
938  SCIP_SET* set, /**< global SCIP settings */
939  SCIP_STAT* stat, /**< problem statistics data */
940  SCIP_PROB* origprob, /**< original problem */
941  SCIP_PROB* transprob, /**< transformed problem after presolve */
942  SCIP_SOL* sol, /**< primal CIP solution */
943  int* insertpos, /**< pointer to store the insert position of that solution */
944  SCIP_Bool* replace /**< pointer to store whether the solution at insertpos should be replaced
945  * (e.g., because it lives in the original space) */
946  )
947 {
948  SCIP_Real obj;
949 
950  obj = SCIPsolGetObj(sol, set, transprob, origprob);
951 
952  /* check if we are willing to check worse solutions; a solution is better if the objective is smaller than the
953  * current cutoff bound; solutions with infinite objective value are never accepted
954  */
955  if( (!set->misc_improvingsols || obj < primal->cutoffbound) && !SCIPsetIsInfinity(set, obj) )
956  {
957  /* find insert position for the solution */
958  (*insertpos) = primalSearchSolPos(primal, set, transprob, origprob, sol);
959  (*replace) = FALSE;
960 
961  /* the solution should be added, if the insertpos is smaller than the maximum number of solutions to be stored
962  * and it does not already exist or it does exist, but the existing solution should be replaced by the new one
963  */
964  if( (*insertpos) < set->limit_maxsol &&
965  (!primalExistsSol(primal, set, stat, origprob, transprob, sol, insertpos, replace) || (*replace)) )
966  return TRUE;
967  }
968 
969  return FALSE;
970 }
971 
972 /** check if we are willing to store the solution candidate for later checking */
973 static
975  SCIP_PRIMAL* primal, /**< primal data */
976  SCIP_SET* set, /**< global SCIP settings */
977  SCIP_STAT* stat, /**< problem statistics data */
978  SCIP_PROB* origprob, /**< original problem */
979  SCIP_SOL* sol, /**< primal CIP solution */
980  int* insertpos /**< pointer to store the insert position of that solution */
981  )
982 {
983  assert(SCIPsolIsOriginal(sol));
984 
985  /* find insert position for the solution */
986  (*insertpos) = primalSearchOrigSolPos(primal, sol);
987 
988  if( (*insertpos) < set->limit_maxorigsol && !primalExistsOrigSol(primal, set, stat, origprob, sol, *insertpos) )
989  return TRUE;
990 
991  return FALSE;
992 }
993 
994 /** adds primal solution to solution storage by copying it */
996  SCIP_PRIMAL* primal, /**< primal data */
997  BMS_BLKMEM* blkmem, /**< block memory */
998  SCIP_SET* set, /**< global SCIP settings */
999  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1000  SCIP_STAT* stat, /**< problem statistics data */
1001  SCIP_PROB* origprob, /**< original problem */
1002  SCIP_PROB* transprob, /**< transformed problem after presolve */
1003  SCIP_TREE* tree, /**< branch and bound tree */
1004  SCIP_REOPT* reopt, /**< reoptimization data structure */
1005  SCIP_LP* lp, /**< current LP data */
1006  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1007  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1008  SCIP_SOL* sol, /**< primal CIP solution */
1009  SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1010  )
1011 {
1012  SCIP_Bool replace;
1013  int insertpos;
1014 
1015  assert(primal != NULL);
1016  assert(transprob != NULL);
1017  assert(origprob != NULL);
1018  assert(sol != NULL);
1019  assert(stored != NULL);
1020 
1021  insertpos = -1;
1022 
1023  if( solOfInterest(primal, set, stat, origprob, transprob, sol, &insertpos, &replace) )
1024  {
1025  SCIP_SOL* solcopy;
1026 #ifdef SCIP_MORE_DEBUG
1027  int i;
1028 #endif
1029 
1030  assert(insertpos >= 0 && insertpos < set->limit_maxsol);
1031 
1032  /* create a copy of the solution */
1033  SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, primal, sol) );
1034 
1035  /* insert copied solution into solution storage */
1036  SCIP_CALL( primalAddSol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1037  tree, reopt, lp, eventqueue, eventfilter, &solcopy, insertpos, replace) );
1038 #ifdef SCIP_MORE_DEBUG
1039  for( i = 0; i < primal->nsols - 1; ++i )
1040  {
1041  assert(SCIPsetIsLE(set, SCIPsolGetObj(primal->sols[i], set, transprob, origprob), SCIPsolGetObj(primal->sols[i+1], set, transprob, origprob)));
1042  }
1043 #endif
1044  *stored = TRUE;
1045  }
1046  else
1047  *stored = FALSE;
1048 
1049  return SCIP_OKAY;
1050 }
1051 
1052 /** adds primal solution to solution storage, frees the solution afterwards */
1054  SCIP_PRIMAL* primal, /**< primal data */
1055  BMS_BLKMEM* blkmem, /**< block memory */
1056  SCIP_SET* set, /**< global SCIP settings */
1057  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1058  SCIP_STAT* stat, /**< problem statistics data */
1059  SCIP_PROB* origprob, /**< original problem */
1060  SCIP_PROB* transprob, /**< transformed problem after presolve */
1061  SCIP_TREE* tree, /**< branch and bound tree */
1062  SCIP_REOPT* reopt, /**< reoptimization data structure */
1063  SCIP_LP* lp, /**< current LP data */
1064  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1065  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1066  SCIP_SOL** sol, /**< pointer to primal CIP solution; is cleared in function call */
1067  SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1068  )
1069 {
1070  SCIP_Bool replace;
1071  int insertpos;
1072 
1073  assert(primal != NULL);
1074  assert(transprob != NULL);
1075  assert(origprob != NULL);
1076  assert(sol != NULL);
1077  assert(*sol != NULL);
1078  assert(stored != NULL);
1079 
1080  insertpos = -1;
1081 
1082  if( solOfInterest(primal, set, stat, origprob, transprob, *sol, &insertpos, &replace) )
1083  {
1084  assert(insertpos >= 0 && insertpos < set->limit_maxsol);
1085 
1086  /* insert solution into solution storage */
1087  SCIP_CALL( primalAddSol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1088  tree, reopt, lp, eventqueue, eventfilter, sol, insertpos, replace) );
1089 
1090  /* clear the pointer, such that the user cannot access the solution anymore */
1091  *sol = NULL;
1092 
1093  *stored = TRUE;
1094  }
1095  else
1096  {
1097  /* the solution is too bad -> free it immediately */
1098  SCIP_CALL( SCIPsolFree(sol, blkmem, primal) );
1099 
1100  *stored = FALSE;
1101  }
1102  assert(*sol == NULL);
1103 
1104  return SCIP_OKAY;
1105 }
1106 
1107 /** adds primal solution to solution candidate storage of original problem space */
1109  SCIP_PRIMAL* primal, /**< primal data */
1110  BMS_BLKMEM* blkmem, /**< block memory */
1111  SCIP_SET* set, /**< global SCIP settings */
1112  SCIP_STAT* stat, /**< problem statistics data */
1113  SCIP_PROB* prob, /**< original problem data */
1114  SCIP_SOL* sol, /**< primal CIP solution; is cleared in function call */
1115  SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1116  )
1117 {
1118  int insertpos;
1119 
1120  assert(primal != NULL);
1121  assert(sol != NULL);
1122  assert(SCIPsolIsOriginal(sol));
1123  assert(stored != NULL);
1124 
1125  insertpos = -1;
1126 
1127  if( origsolOfInterest(primal, set, stat, prob, sol, &insertpos) )
1128  {
1129  SCIP_SOL* solcopy;
1130 
1131  assert(insertpos >= 0 && insertpos < set->limit_maxorigsol);
1132 
1133  /* create a copy of the solution */
1134  SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, primal, sol) );
1135 
1136  /* insert solution into solution storage */
1137  SCIP_CALL( primalAddOrigSol(primal, blkmem, set, prob, solcopy, insertpos) );
1138 
1139  *stored = TRUE;
1140  }
1141  else
1142  *stored = FALSE;
1143 
1144  return SCIP_OKAY;
1145 }
1146 
1147 /** adds primal solution to solution candidate storage of original problem space, frees the solution afterwards */
1149  SCIP_PRIMAL* primal, /**< primal data */
1150  BMS_BLKMEM* blkmem, /**< block memory */
1151  SCIP_SET* set, /**< global SCIP settings */
1152  SCIP_STAT* stat, /**< problem statistics data */
1153  SCIP_PROB* prob, /**< original problem data */
1154  SCIP_SOL** sol, /**< pointer to primal CIP solution; is cleared in function call */
1155  SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1156  )
1157 {
1158  int insertpos;
1159 
1160  assert(primal != NULL);
1161  assert(sol != NULL);
1162  assert(*sol != NULL);
1163  assert(SCIPsolIsOriginal(*sol));
1164  assert(stored != NULL);
1165 
1166  insertpos = -1;
1167 
1168  if( origsolOfInterest(primal, set, stat, prob, *sol, &insertpos) )
1169  {
1170  assert(insertpos >= 0 && insertpos < set->limit_maxorigsol);
1171 
1172  /* insert solution into solution storage */
1173  SCIP_CALL( primalAddOrigSol(primal, blkmem, set, prob, *sol, insertpos) );
1174 
1175  /* clear the pointer, such that the user cannot access the solution anymore */
1176  *sol = NULL;
1177 
1178  *stored = TRUE;
1179  }
1180  else
1181  {
1182  /* the solution is too bad -> free it immediately */
1183  SCIP_CALL( SCIPsolFree(sol, blkmem, primal) );
1184 
1185  *stored = FALSE;
1186  }
1187  assert(*sol == NULL);
1188 
1189  return SCIP_OKAY;
1190 }
1191 
1192 /** links temporary solution of primal data to current solution */
1193 static
1195  SCIP_PRIMAL* primal, /**< primal data */
1196  BMS_BLKMEM* blkmem, /**< block memory */
1197  SCIP_SET* set, /**< global SCIP settings */
1198  SCIP_STAT* stat, /**< problem statistics data */
1199  SCIP_PROB* prob, /**< transformed problem data */
1200  SCIP_TREE* tree, /**< branch and bound tree */
1201  SCIP_LP* lp, /**< current LP data */
1202  SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */
1203  )
1204 {
1205  assert(primal != NULL);
1206 
1207  if( primal->currentsol == NULL )
1208  {
1209  SCIP_CALL( SCIPsolCreateCurrentSol(&primal->currentsol, blkmem, set, stat, prob, primal, tree, lp, heur) );
1210  }
1211  else
1212  {
1213  SCIP_CALL( SCIPsolLinkCurrentSol(primal->currentsol, set, stat, prob, tree, lp) );
1214  SCIPsolSetHeur(primal->currentsol, heur);
1215  }
1216 
1217  return SCIP_OKAY;
1218 }
1219 
1220 /** adds current LP/pseudo solution to solution storage */
1222  SCIP_PRIMAL* primal, /**< primal data */
1223  BMS_BLKMEM* blkmem, /**< block memory */
1224  SCIP_SET* set, /**< global SCIP settings */
1225  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1226  SCIP_STAT* stat, /**< problem statistics data */
1227  SCIP_PROB* origprob, /**< original problem */
1228  SCIP_PROB* transprob, /**< transformed problem after presolve */
1229  SCIP_TREE* tree, /**< branch and bound tree */
1230  SCIP_REOPT* reopt, /**< reoptimization data structure */
1231  SCIP_LP* lp, /**< current LP data */
1232  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1233  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1234  SCIP_HEUR* heur, /**< heuristic that found the solution (or NULL if it's from the tree) */
1235  SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1236  )
1237 {
1238  assert(primal != NULL);
1239 
1240  /* link temporary solution to current solution */
1241  SCIP_CALL( primalLinkCurrentSol(primal, blkmem, set, stat, transprob, tree, lp, heur) );
1242 
1243  /* add solution to solution storage */
1244  SCIP_CALL( SCIPprimalAddSol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1245  tree, reopt, lp, eventqueue, eventfilter, primal->currentsol, stored) );
1246 
1247  return SCIP_OKAY;
1248 }
1249 
1250 /** checks primal solution; if feasible, adds it to storage by copying it */
1252  SCIP_PRIMAL* primal, /**< primal data */
1253  BMS_BLKMEM* blkmem, /**< block memory */
1254  SCIP_SET* set, /**< global SCIP settings */
1255  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1256  SCIP_STAT* stat, /**< problem statistics data */
1257  SCIP_PROB* origprob, /**< original problem */
1258  SCIP_PROB* transprob, /**< transformed problem after presolve */
1259  SCIP_TREE* tree, /**< branch and bound tree */
1260  SCIP_REOPT* reopt, /**< reoptimization data structure */
1261  SCIP_LP* lp, /**< current LP data */
1262  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1263  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1264  SCIP_SOL* sol, /**< primal CIP solution */
1265  SCIP_Bool printreason, /**< should all reasons of violations be printed? */
1266  SCIP_Bool checkbounds, /**< should the bounds of the variables be checked? */
1267  SCIP_Bool checkintegrality, /**< has integrality to be checked? */
1268  SCIP_Bool checklprows, /**< have current LP rows to be checked? */
1269  SCIP_Bool* stored /**< stores whether given solution was feasible and good enough to keep */
1270  )
1271 {
1272  SCIP_Bool feasible;
1273  SCIP_Bool replace;
1274  int insertpos;
1275 
1276  assert(primal != NULL);
1277  assert(set != NULL);
1278  assert(transprob != NULL);
1279  assert(origprob != NULL);
1280  assert(tree != NULL);
1281  assert(sol != NULL);
1282  assert(stored != NULL);
1283 
1284  /* if we want to solve exactly, the constraint handlers cannot rely on the LP's feasibility */
1285  checklprows = checklprows || set->misc_exactsolve;
1286 
1287  insertpos = -1;
1288 
1289  if( solOfInterest(primal, set, stat, origprob, transprob, sol, &insertpos, &replace) )
1290  {
1291  /* check solution for feasibility */
1292  SCIP_CALL( SCIPsolCheck(sol, set, messagehdlr, blkmem, stat, transprob, printreason, checkbounds, checkintegrality, checklprows, &feasible) );
1293  }
1294  else
1295  feasible = FALSE;
1296 
1297  if( feasible )
1298  {
1299  SCIP_SOL* solcopy;
1300 
1301  assert(insertpos >= 0 && insertpos < set->limit_maxsol);
1302 
1303  /* create a copy of the solution */
1304  SCIP_CALL( SCIPsolCopy(&solcopy, blkmem, set, stat, primal, sol) );
1305 
1306  /* insert copied solution into solution storage */
1307  SCIP_CALL( primalAddSol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1308  tree, reopt, lp, eventqueue, eventfilter, &solcopy, insertpos, replace) );
1309 
1310  *stored = TRUE;
1311  }
1312  else
1313  *stored = FALSE;
1314 
1315  return SCIP_OKAY;
1316 }
1317 
1318 /** checks primal solution; if feasible, adds it to storage; solution is freed afterwards */
1320  SCIP_PRIMAL* primal, /**< primal data */
1321  BMS_BLKMEM* blkmem, /**< block memory */
1322  SCIP_SET* set, /**< global SCIP settings */
1323  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1324  SCIP_STAT* stat, /**< problem statistics data */
1325  SCIP_PROB* origprob, /**< original problem */
1326  SCIP_PROB* transprob, /**< transformed problem after presolve */
1327  SCIP_TREE* tree, /**< branch and bound tree */
1328  SCIP_REOPT* reopt, /**< reoptimization data structure */
1329  SCIP_LP* lp, /**< current LP data */
1330  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1331  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1332  SCIP_SOL** sol, /**< pointer to primal CIP solution; is cleared in function call */
1333  SCIP_Bool printreason, /**< should all the reasons of violations be printed? */
1334  SCIP_Bool checkbounds, /**< should the bounds of the variables be checked? */
1335  SCIP_Bool checkintegrality, /**< has integrality to be checked? */
1336  SCIP_Bool checklprows, /**< have current LP rows to be checked? */
1337  SCIP_Bool* stored /**< stores whether solution was feasible and good enough to keep */
1338  )
1339 {
1340  SCIP_Bool feasible;
1341  SCIP_Bool replace;
1342  int insertpos;
1343 
1344  assert(primal != NULL);
1345  assert(transprob != NULL);
1346  assert(origprob != NULL);
1347  assert(tree != NULL);
1348  assert(sol != NULL);
1349  assert(*sol != NULL);
1350  assert(stored != NULL);
1351 
1352  *stored = FALSE;
1353 
1354  /* if we want to solve exactly, the constraint handlers cannot rely on the LP's feasibility */
1355  checklprows = checklprows || set->misc_exactsolve;
1356 
1357  insertpos = -1;
1358 
1359  if( solOfInterest(primal, set, stat, origprob, transprob, *sol, &insertpos, &replace) )
1360  {
1361  /* check solution for feasibility */
1362  SCIP_CALL( SCIPsolCheck(*sol, set, messagehdlr, blkmem, stat, transprob, printreason, checkbounds, checkintegrality, checklprows, &feasible) );
1363  }
1364  else
1365  feasible = FALSE;
1366 
1367  if( feasible )
1368  {
1369  assert(insertpos >= 0 && insertpos < set->limit_maxsol);
1370 
1371  /* insert solution into solution storage */
1372  SCIP_CALL( primalAddSol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1373  tree, reopt, lp, eventqueue, eventfilter, sol, insertpos, replace) );
1374 
1375  /* clear the pointer, such that the user cannot access the solution anymore */
1376  *sol = NULL;
1377  *stored = TRUE;
1378  }
1379  else
1380  {
1381  /* the solution is too bad or infeasible -> free it immediately */
1382  SCIP_CALL( SCIPsolFree(sol, blkmem, primal) );
1383  *stored = FALSE;
1384  }
1385  assert(*sol == NULL);
1386 
1387  return SCIP_OKAY;
1388 }
1389 
1390 /** checks current LP/pseudo solution; if feasible, adds it to storage */
1392  SCIP_PRIMAL* primal, /**< primal data */
1393  BMS_BLKMEM* blkmem, /**< block memory */
1394  SCIP_SET* set, /**< global SCIP settings */
1395  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1396  SCIP_STAT* stat, /**< problem statistics data */
1397  SCIP_PROB* origprob, /**< original problem */
1398  SCIP_PROB* transprob, /**< transformed problem after presolve */
1399  SCIP_TREE* tree, /**< branch and bound tree */
1400  SCIP_REOPT* reopt, /**< reoptimization data structure */
1401  SCIP_LP* lp, /**< current LP data */
1402  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1403  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1404  SCIP_HEUR* heur, /**< heuristic that found the solution (or NULL if it's from the tree) */
1405  SCIP_Bool printreason, /**< should all reasons of violations be printed? */
1406  SCIP_Bool checkintegrality, /**< has integrality to be checked? */
1407  SCIP_Bool checklprows, /**< have current LP rows to be checked? */
1408  SCIP_Bool* stored /**< stores whether given solution was good enough to keep */
1409  )
1410 {
1411  assert(primal != NULL);
1412 
1413  /* link temporary solution to current solution */
1414  SCIP_CALL( primalLinkCurrentSol(primal, blkmem, set, stat, transprob, tree, lp, heur) );
1415 
1416  /* add solution to solution storage */
1417  SCIP_CALL( SCIPprimalTrySol(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1418  tree, reopt, lp, eventqueue, eventfilter, primal->currentsol,
1419  printreason, FALSE, checkintegrality, checklprows, stored) );
1420 
1421  return SCIP_OKAY;
1422 }
1423 
1424 /** inserts solution into the global array of all existing primal solutions */
1426  SCIP_PRIMAL* primal, /**< primal data */
1427  SCIP_SET* set, /**< global SCIP settings */
1428  SCIP_SOL* sol /**< primal CIP solution */
1429  )
1430 {
1431  assert(primal != NULL);
1432  assert(sol != NULL);
1433  assert(SCIPsolGetPrimalIndex(sol) == -1);
1434 
1435  /* allocate memory for solution storage */
1436  SCIP_CALL( ensureExistingsolsSize(primal, set, primal->nexistingsols+1) );
1437 
1438  /* append solution */
1439  SCIPsolSetPrimalIndex(sol, primal->nexistingsols);
1440  primal->existingsols[primal->nexistingsols] = sol;
1441  primal->nexistingsols++;
1442 
1443  return SCIP_OKAY;
1444 }
1445 
1446 /** removes solution from the global array of all existing primal solutions */
1448  SCIP_PRIMAL* primal, /**< primal data */
1449  SCIP_SOL* sol /**< primal CIP solution */
1450  )
1451 {
1452  int idx;
1453 
1454  assert(primal != NULL);
1455  assert(sol != NULL);
1456 
1457 #ifndef NDEBUG
1458  for( idx = 0; idx < primal->nexistingsols; ++idx )
1459  {
1460  assert(idx == SCIPsolGetPrimalIndex(primal->existingsols[idx]));
1461  }
1462 #endif
1463 
1464  /* remove solution */
1465  idx = SCIPsolGetPrimalIndex(sol);
1466  assert(0 <= idx && idx < primal->nexistingsols);
1467  assert(sol == primal->existingsols[idx]);
1468  if( idx < primal->nexistingsols-1 )
1469  {
1470  primal->existingsols[idx] = primal->existingsols[primal->nexistingsols-1];
1471  SCIPsolSetPrimalIndex(primal->existingsols[idx], idx);
1472  }
1473  primal->nexistingsols--;
1474 }
1475 
1476 /** updates all existing primal solutions after a change in a variable's objective value */
1478  SCIP_PRIMAL* primal, /**< primal data */
1479  SCIP_VAR* var, /**< problem variable */
1480  SCIP_Real oldobj, /**< old objective value */
1481  SCIP_Real newobj /**< new objective value */
1482  )
1483 {
1484  int i;
1485 
1486  assert(primal != NULL);
1487 
1488  for( i = 0; i < primal->nexistingsols; ++i )
1489  {
1490  if( !SCIPsolIsOriginal(primal->existingsols[i]) )
1491  SCIPsolUpdateVarObj(primal->existingsols[i], var, oldobj, newobj);
1492  }
1493 }
1494 
1495 /** retransforms all existing solutions to original problem space */
1497  SCIP_PRIMAL* primal, /**< primal data */
1498  SCIP_SET* set, /**< global SCIP settings */
1499  SCIP_STAT* stat, /**< problem statistics data */
1500  SCIP_PROB* origprob, /**< original problem */
1501  SCIP_PROB* transprob /**< transformed problem */
1502  )
1503 {
1504  SCIP_Bool hasinfval;
1505  int i;
1506 
1507  assert(primal != NULL);
1508 
1509  for( i = 0; i < primal->nsols; ++i )
1510  {
1511  if( SCIPsolGetOrigin(primal->sols[i]) == SCIP_SOLORIGIN_ZERO )
1512  {
1513  SCIP_CALL( SCIPsolRetransform(primal->sols[i], set, stat, origprob, transprob, &hasinfval) );
1514  }
1515  }
1516 
1517  return SCIP_OKAY;
1518 }
1519 
1520 /** tries to transform original solution to the transformed problem space */
1522  SCIP_PRIMAL* primal, /**< primal data */
1523  SCIP_SOL* sol, /**< primal solution */
1524  BMS_BLKMEM* blkmem, /**< block memory */
1525  SCIP_SET* set, /**< global SCIP settings */
1526  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1527  SCIP_STAT* stat, /**< problem statistics data */
1528  SCIP_PROB* origprob, /**< original problem */
1529  SCIP_PROB* transprob, /**< transformed problem after presolve */
1530  SCIP_TREE* tree, /**< branch and bound tree */
1531  SCIP_REOPT* reopt, /**< reoptimization data structure */
1532  SCIP_LP* lp, /**< current LP data */
1533  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1534  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
1535  SCIP_Real* solvals, /**< array for internal use to store solution values, or NULL;
1536  * if the method is called multiple times in a row, an array with size >=
1537  * number of active variables should be given for performance reasons */
1538  SCIP_Bool* solvalset, /**< array for internal use to store which solution values were set, or NULL;
1539  * if the method is called multiple times in a row, an array with size >=
1540  * number of active variables should be given for performance reasons */
1541  int solvalssize, /**< size of solvals and solvalset arrays, should be >= number of active
1542  * variables */
1543  SCIP_Bool* added /**< pointer to store whether the solution was added */
1544  )
1545 {
1546  SCIP_VAR** origvars;
1547  SCIP_VAR** transvars;
1548  SCIP_VAR* var;
1549  SCIP_Real* localsolvals;
1550  SCIP_Bool* localsolvalset;
1551  SCIP_Real solval;
1552  SCIP_Real scalar;
1553  SCIP_Real constant;
1554  SCIP_Bool localarrays;
1555  SCIP_Bool feasible;
1556  int norigvars;
1557  int ntransvars;
1558  int nvarsset;
1559  int v;
1560 
1561  assert(origprob != NULL);
1562  assert(transprob != NULL);
1563  assert(SCIPsolIsOriginal(sol));
1564  assert(solvalssize == 0 || solvals != NULL);
1565  assert(solvalssize == 0 || solvalset != NULL);
1566 
1567  origvars = origprob->vars;
1568  norigvars = origprob->nvars;
1569  transvars = transprob->vars;
1570  ntransvars = transprob->nvars;
1571  assert(solvalssize == 0 || solvalssize >= ntransvars);
1572 
1573  SCIPdebugMessage("try to transfer original solution %p with objective %g into the transformed problem space\n",
1574  (void*)sol, SCIPsolGetOrigObj(sol));
1575 
1576  /* if no solvals and solvalset arrays are given, allocate local ones, otherwise use the given ones */
1577  localarrays = (solvalssize == 0);
1578  if( localarrays )
1579  {
1580  SCIP_CALL( SCIPsetAllocBufferArray(set, &localsolvals, ntransvars) );
1581  SCIP_CALL( SCIPsetAllocBufferArray(set, &localsolvalset, ntransvars) );
1582  }
1583  else
1584  {
1585  localsolvals = solvals;
1586  localsolvalset = solvalset;
1587  }
1588 
1589  BMSclearMemoryArray(localsolvalset, ntransvars);
1590  feasible = TRUE;
1591  (*added) = FALSE;
1592  nvarsset = 0;
1593 
1594  /* for each original variable, get the corresponding active, fixed or multi-aggregated variable;
1595  * if it resolves to an active variable, we set its solution value or check whether an already stored solution value
1596  * is consistent; if it resolves to a fixed variable, we check that the fixing matches the original solution value;
1597  * multi-aggregated variables are skipped, because their value is defined by setting solution values for the active
1598  * variables, anyway
1599  */
1600  for( v = 0; v < norigvars && feasible; ++v )
1601  {
1602  var = origvars[v];
1603 
1604  solval = SCIPsolGetVal(sol, set, stat, var);
1605 
1606  /* get corresponding active, fixed, or multi-aggregated variable */
1607  scalar = 1.0;
1608  constant = 0.0;
1609  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &constant) );
1612 
1613  /* check whether the fixing corresponds to the solution value of the original variable */
1614  if( scalar == 0.0 )
1615  {
1616  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED ||
1617  (SCIPsetIsInfinity(set, constant) || SCIPsetIsInfinity(set, -constant)));
1618 
1619  if( !SCIPsetIsEQ(set, solval, constant) )
1620  {
1621  SCIPdebugMessage("original variable <%s> (solval=%g) resolves to fixed variable <%s> (original solval=%g)\n",
1622  SCIPvarGetName(origvars[v]), solval, SCIPvarGetName(var), constant);
1623  feasible = FALSE;
1624  }
1625  }
1626  else if( SCIPvarIsActive(var) )
1627  {
1628  /* if we already assigned a solution value to the transformed variable, check that it corresponds to the
1629  * value obtained from the currently regarded original variable
1630  */
1631  if( localsolvalset[SCIPvarGetProbindex(var)] )
1632  {
1633  if( !SCIPsetIsEQ(set, solval, scalar * localsolvals[SCIPvarGetProbindex(var)] + constant) )
1634  {
1635  SCIPdebugMessage("original variable <%s> (solval=%g) resolves to active variable <%s> with assigned solval %g (original solval=%g)\n",
1636  SCIPvarGetName(origvars[v]), solval, SCIPvarGetName(var), localsolvals[SCIPvarGetProbindex(var)],
1637  scalar * localsolvals[SCIPvarGetProbindex(var)] + constant);
1638  feasible = FALSE;
1639  }
1640  }
1641  /* assign solution value to the transformed variable */
1642  else
1643  {
1644  assert(scalar != 0.0);
1645 
1646  localsolvals[SCIPvarGetProbindex(var)] = (solval - constant) / scalar;
1647  localsolvalset[SCIPvarGetProbindex(var)] = TRUE;
1648  ++nvarsset;
1649  }
1650  }
1651 #ifndef NDEBUG
1652  /* we do not have to handle multi-aggregated variables here, since by assigning values to all active variabes,
1653  * we implicitly assign values to the multi-aggregated variables, too
1654  */
1655  else
1656  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
1657 #endif
1658  }
1659 
1660  /* if the solution values of fixed and active variables lead to no contradiction, construct solution and try it */
1661  if( feasible )
1662  {
1663  SCIP_SOL* transsol;
1664 
1665  SCIP_CALL( SCIPsolCreate(&transsol, blkmem, set, stat, primal, tree, SCIPsolGetHeur(sol)) );
1666 
1667  /* set solution values for variables to which we assigned a value */
1668  for( v = 0; v < ntransvars; ++v )
1669  {
1670  if( localsolvalset[v] )
1671  {
1672  SCIP_CALL( SCIPsolSetVal(transsol, set, stat, tree, transvars[v], localsolvals[v]) );
1673  }
1674  }
1675 
1676  SCIP_CALL( SCIPprimalTrySolFree(primal, blkmem, set, messagehdlr, stat, origprob, transprob,
1677  tree, reopt, lp, eventqueue, eventfilter, &transsol, FALSE, TRUE, TRUE, TRUE, added) );
1678 
1679  SCIPdebugMessage("solution transferred, %d/%d active variables set (stored=%u)\n", nvarsset, ntransvars, *added);
1680  }
1681  else
1682  (*added) = FALSE;
1683 
1684  /* free local arrays, if needed */
1685  if( localarrays )
1686  {
1687  SCIPsetFreeBufferArray(set, &localsolvalset);
1688  SCIPsetFreeBufferArray(set, &localsolvals);
1689  }
1690 
1691  return SCIP_OKAY;
1692 }
SCIP_Real cutoffbound
Definition: struct_primal.h:45
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:1194
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 checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: primal.c:1251
SCIP_RETCODE SCIPsolUnlink(SCIP_SOL *sol, SCIP_SET *set, SCIP_PROB *prob)
Definition: sol.c:943
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5031
internal methods for managing events
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition: sol.c:2193
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5089
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16341
internal methods for storing primal CIP solutions
void SCIPprimalSolFreed(SCIP_PRIMAL *primal, SCIP_SOL *sol)
Definition: primal.c:1447
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:103
internal methods for branch and bound tree
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 checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: primal.c:1319
static SCIP_RETCODE primalAddOrigSol(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_SOL *sol, int insertpos)
Definition: primal.c:666
SCIP_SOLORIGIN SCIPsolGetOrigin(SCIP_SOL *sol)
Definition: sol.c:2110
static SCIP_RETCODE primalSetUpperbound(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_Real upperbound)
Definition: primal.c:241
SCIP_RETCODE SCIPdispPrintLine(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, FILE *file, SCIP_Bool forcedisplay, SCIP_Bool endline)
Definition: disp.c:362
int nrunsbeforefirst
Definition: struct_stat.h:218
SCIP_RETCODE SCIPeventChgType(SCIP_EVENT *event, SCIP_EVENTTYPE eventtype)
Definition: event.c:927
int SCIPsolGetDepth(SCIP_SOL *sol)
Definition: sol.c:2183
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:4893
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:1108
SCIP_RETCODE SCIPsolLinkCurrentSol(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_LP *lp)
Definition: sol.c:883
SCIP_SOL ** sols
Definition: struct_primal.h:47
SCIP_SOL * currentsol
Definition: struct_primal.h:49
#define FALSE
Definition: def.h:53
SCIP_RETCODE SCIPeventProcess(SCIP_EVENT *event, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter)
Definition: event.c:1418
int limit_maxorigsol
Definition: struct_set.h:242
SCIP_RETCODE SCIPsolCopy(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PRIMAL *primal, SCIP_SOL *sourcesol)
Definition: sol.c:334
SCIP_STAGE stage
Definition: struct_set.h:57
#define TRUE
Definition: def.h:52
#define SCIPdebug(x)
Definition: pub_message.h:74
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
static SCIP_RETCODE ensureSolsSize(SCIP_PRIMAL *primal, SCIP_SET *set, int num)
Definition: primal.c:47
void SCIPsolSetPrimalIndex(SCIP_SOL *sol, int primalindex)
Definition: sol.c:2213
SCIP_Real SCIPprobInternObjval(SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_SET *set, SCIP_Real objval)
Definition: prob.c:1971
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1775
int SCIPtreeGetCurrentDepth(SCIP_TREE *tree)
Definition: tree.c:7957
SCIP_Bool SCIPsolsAreEqual(SCIP_SOL *sol1, SCIP_SOL *sol2, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob)
Definition: sol.c:1806
SCIP_Real SCIPsetCutoffbounddelta(SCIP_SET *set)
Definition: set.c:5006
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:4626
SCIP_Longint nsolsfound
Definition: struct_primal.h:38
#define SCIPdebugMessage
Definition: pub_message.h:77
int limit_maxsol
Definition: struct_set.h:241
methods for creating output for visualization tools (VBC, BAK)
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1782
#define BMSfreeMemory(ptr)
Definition: memory.h:100
SCIP_Bool misc_improvingsols
Definition: struct_set.h:321
SCIP_VISUAL * visual
Definition: struct_stat.h:137
internal methods for LP management
internal methods for collecting primal CIP solutions and primal informations
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1190
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5125
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16460
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:1221
SCIP_RETCODE SCIPprimalUpdateObjlimit(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition: primal.c:326
SCIP_Real SCIPsolGetTime(SCIP_SOL *sol)
Definition: sol.c:2153
SCIP_Real SCIPprobGetObjlim(SCIP_PROB *prob, SCIP_SET *set)
Definition: prob.c:2126
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5071
SCIP_RETCODE SCIPeventChgSol(SCIP_EVENT *event, SCIP_SOL *sol)
Definition: event.c:1198
SCIP_Real SCIPsolGetObj(SCIP_SOL *sol, SCIP_SET *set, SCIP_PROB *transprob, SCIP_PROB *origprob)
Definition: sol.c:1381
void SCIPsolUpdateVarsum(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_Real weight)
Definition: sol.c:1618
internal methods for storing and manipulating the main problem
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Longint nbestsolsfound
Definition: struct_primal.h:41
static int primalSearchOrigSolPos(SCIP_PRIMAL *primal, SCIP_SOL *sol)
Definition: primal.c:767
SCIP_Longint bestsolnode
Definition: struct_stat.h:84
SCIP_Bool SCIPtreeInRepropagation(SCIP_TREE *tree)
Definition: tree.c:7930
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:637
int SCIPsolGetRunnum(SCIP_SOL *sol)
Definition: sol.c:2163
void SCIPsolSetHeur(SCIP_SOL *sol, SCIP_HEUR *heur)
Definition: sol.c:2234
SCIP_HEUR * firstprimalheur
Definition: struct_stat.h:138
SCIP_RETCODE SCIPsolSetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_VAR *var, SCIP_Real val)
Definition: sol.c:972
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5609
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:802
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 printzeros)
Definition: sol.c:1866
#define REALABS(x)
Definition: def.h:148
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:479
SCIP_Bool SCIPprobIsObjIntegral(SCIP_PROB *prob)
Definition: prob.c:2102
internal methods for global SCIP settings
#define SCIP_CALL(x)
Definition: def.h:263
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5517
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5053
SCIP_RETCODE SCIPprimalRetransformSolutions(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob)
Definition: primal.c:1496
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 checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: primal.c:1391
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5473
SCIP_RETCODE SCIPsolTransform(SCIP_SOL *sol, SCIP_SOL **transsol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal)
Definition: sol.c:369
SCIP_RETCODE SCIPprimalSetCutoffbound(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, 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:188
data structures and methods for collecting reoptimization information
internal methods for problem variables
SCIP_RETCODE SCIPprimalSolCreated(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_SOL *sol)
Definition: primal.c:1425
#define SCIP_Bool
Definition: def.h:50
static SCIP_Bool origsolOfInterest(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_SOL *sol, int *insertpos)
Definition: primal.c:974
void SCIPprimalUpdateVarObj(SCIP_PRIMAL *primal, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: primal.c:1477
SCIP_Real SCIPsolGetOrigObj(SCIP_SOL *sol)
Definition: sol.c:2130
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:269
SCIP_Longint SCIPsolGetNodenum(SCIP_SOL *sol)
Definition: sol.c:2173
SCIP_RETCODE SCIPsolRetransform(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *origprob, SCIP_PROB *transprob, SCIP_Bool *hasinfval)
Definition: sol.c:1646
void SCIPsolOrigAddObjval(SCIP_SOL *sol, SCIP_Real addval)
Definition: sol.c:2141
static SCIP_RETCODE primalSetCutoffbound(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_EVENTQUEUE *eventqueue, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_Real cutoffbound)
Definition: primal.c:156
void SCIPprobSetObjlim(SCIP_PROB *prob, SCIP_Real objlim)
Definition: prob.c:1403
SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
Definition: sol.c:2120
SCIP_Longint nnodesbeforefirst
Definition: struct_stat.h:92
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:936
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:1148
SCIP_RETCODE SCIPprimalSetUpperbound(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_Real upperbound)
Definition: primal.c:295
SCIP_Bool misc_exactsolve
Definition: struct_set.h:312
#define SCIP_EVENTTYPE_BESTSOLFOUND
Definition: type_event.h:82
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:1053
#define SCIP_EVENTTYPE_POORSOLFOUND
Definition: type_event.h:81
SCIP_RETCODE SCIPlpSetCutoffbound(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_Real cutoffbound)
Definition: lp.c:12476
SCIP_Bool SCIPprimalUpperboundIsSol(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_PROB *transprob, SCIP_PROB *origprob)
Definition: primal.c:465
SCIP_NODE * SCIPtreeGetCurrentNode(SCIP_TREE *tree)
Definition: tree.c:7940
public methods for message output
SCIP_Real upperbound
Definition: struct_primal.h:44
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16648
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5107
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:995
SCIP_Bool misc_transorigsols
Definition: struct_set.h:324
int SCIPsolGetPrimalIndex(SCIP_SOL *sol)
Definition: sol.c:2203
void SCIPsolUpdateVarObj(SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: sol.c:1398
#define SCIP_Real
Definition: def.h:124
internal methods for problem statistics
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 checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *feasible)
Definition: sol.c:1417
SCIP_VAR ** vars
Definition: struct_prob.h:54
SCIP_Real firstprimaltime
Definition: struct_stat.h:98
#define MIN(x, y)
Definition: memory.c:63
SCIP_Real firstprimalbound
Definition: struct_stat.h:97
#define BMSallocMemory(ptr)
Definition: memory.h:74
#define SCIP_INVALID
Definition: def.h:144
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:82
SCIP_RETCODE SCIPprimalUpdateObjoffset(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition: primal.c:365
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:1521
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:4915
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:2283
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16628
SCIP_Real SCIPprobExternObjval(SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_SET *set, SCIP_Real objval)
Definition: prob.c:1949
static int primalSearchSolPos(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_SOL *sol)
Definition: primal.c:717
void SCIPprimalAddOrigObjoffset(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_Real addval)
Definition: primal.c:431
SCIP_RETCODE SCIPprimalCreate(SCIP_PRIMAL **primal)
Definition: primal.c:92
SCIP_RETCODE SCIPtreeCutoff(SCIP_TREE *tree, SCIP_REOPT *reopt, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real cutoffbound)
Definition: tree.c:4892
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
common defines and data types used in all packages of SCIP
SCIP_Longint nnodes
Definition: struct_stat.h:64
static SCIP_RETCODE ensureExistingsolsSize(SCIP_PRIMAL *primal, SCIP_SET *set, int num)
Definition: primal.c:70
static SCIP_Bool primalExistsOrigSol(SCIP_PRIMAL *primal, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_SOL *sol, int insertpos)
Definition: primal.c:884
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:392
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:11864
SCIP_RETCODE SCIPprimalFree(SCIP_PRIMAL **primal, BMS_BLKMEM *blkmem)
Definition: primal.c:118
int firstprimaldepth
Definition: struct_stat.h:219
#define SCIP_ALLOC(x)
Definition: def.h:274
int existingsolssize
Definition: struct_primal.h:54
void SCIPvisualUpperbound(SCIP_VISUAL *visual, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real upperbound)
Definition: visual.c:749
SCIP_Longint nlimsolsfound
Definition: struct_primal.h:39
SCIP_SOL ** existingsols
Definition: struct_primal.h:48
void SCIPvisualFoundSolution(SCIP_VISUAL *visual, SCIP_SET *set, SCIP_STAT *stat, SCIP_NODE *node, SCIP_Bool bettersol, SCIP_SOL *sol)
Definition: visual.c:653
SCIP_RETCODE SCIPsolFree(SCIP_SOL **sol, BMS_BLKMEM *blkmem, SCIP_PRIMAL *primal)
Definition: sol.c:696
internal methods for displaying runtime statistics