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