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