Scippy

SCIP

Solving Constraint Integer Programs

sol.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 sol.c
17  * @brief methods for storing primal CIP solutions
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/clock.h"
29 #include "scip/misc.h"
30 #include "scip/lp.h"
31 #include "scip/nlp.h"
32 #include "scip/relax.h"
33 #include "scip/var.h"
34 #include "scip/prob.h"
35 #include "scip/sol.h"
36 #include "scip/primal.h"
37 #include "scip/tree.h"
38 #include "scip/cons.h"
39 #include "scip/pub_message.h"
40 
41 #ifndef NDEBUG
42 #include "scip/struct_sol.h"
43 #endif
44 
45 
46 
47 /** clears solution arrays of primal CIP solution */
48 static
50  SCIP_SOL* sol /**< primal CIP solution */
51  )
52 {
53  assert(sol != NULL);
54 
56  sol->hasinfval = FALSE;
57 
58  return SCIP_OKAY;
59 }
60 
61 /** sets value of variable in the solution's array */
62 static
64  SCIP_SOL* sol, /**< primal CIP solution */
65  SCIP_SET* set, /**< global SCIP settings */
66  SCIP_VAR* var, /**< problem variable */
67  SCIP_Real val /**< value to set variable to */
68  )
69 {
70  int idx;
71 
72  assert(sol != NULL);
73 
74  idx = SCIPvarGetIndex(var);
75 
76  /* from now on, variable must not be deleted */
78 
79  /* mark the variable valid */
80  SCIP_CALL( SCIPboolarraySetVal(sol->valid, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, TRUE) );
81 
82  /* set the value in the solution array */
83  SCIP_CALL( SCIPrealarraySetVal(sol->vals, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, val) );
84 
85  /* store whether the solution has infinite values assigned to variables */
86  if( val != SCIP_UNKNOWN ) /*lint !e777*/
87  sol->hasinfval = (sol->hasinfval || SCIPsetIsInfinity(set, val) || SCIPsetIsInfinity(set, -val));
88 
89  return SCIP_OKAY;
90 }
91 
92 /** increases value of variable in the solution's array */
93 static
95  SCIP_SOL* sol, /**< primal CIP solution */
96  SCIP_SET* set, /**< global SCIP settings */
97  SCIP_VAR* var, /**< problem variable */
98  SCIP_Real incval /**< increase of variable's solution value */
99  )
100 {
101  int idx;
102 
103  assert(sol != NULL);
104 
105  idx = SCIPvarGetIndex(var);
106 
107  /* from now on, variable must not be deleted */
109 
110  /* if the variable was not valid, mark it to be valid and set the value to the incval (it is 0.0 if not valid) */
111  if( !SCIPboolarrayGetVal(sol->valid, idx) )
112  {
113  /* mark the variable valid */
114  SCIP_CALL( SCIPboolarraySetVal(sol->valid, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, TRUE) );
115 
116  /* set the value in the solution array */
117  SCIP_CALL( SCIPrealarraySetVal(sol->vals, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, incval) );
118  }
119  else
120  {
121  /* increase the value in the solution array */
122  SCIP_CALL( SCIPrealarrayIncVal(sol->vals, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, incval) );
123  }
124 
125  /* store whether the solution has infinite values assigned to variables */
126  incval = SCIPrealarrayGetVal(sol->vals, idx);
127  if( incval != SCIP_UNKNOWN ) /*lint !e777*/
128  sol->hasinfval = (sol->hasinfval || SCIPsetIsInfinity(set, incval) || SCIPsetIsInfinity(set, -incval));
129 
130  return SCIP_OKAY;
131 }
132 
133 /** returns the value of the variable in the given solution */
134 static
136  SCIP_SOL* sol, /**< primal CIP solution */
137  SCIP_VAR* var /**< problem variable */
138  )
139 {
140  int idx;
141 
142  assert(sol != NULL);
143 
144  idx = SCIPvarGetIndex(var);
145 
146  /* check, if the variable's value is valid */
147  if( SCIPboolarrayGetVal(sol->valid, idx) )
148  {
149  return SCIPrealarrayGetVal(sol->vals, idx);
150  }
151  else
152  {
153  /* return the variable's value corresponding to the origin */
154  switch( sol->solorigin )
155  {
157  case SCIP_SOLORIGIN_ZERO:
158  return 0.0;
159 
161  return SCIPvarGetLPSol(var);
162 
164  return SCIPvarGetNLPSol(var);
165 
167  return SCIPvarGetRelaxSolTransVar(var);
168 
170  return SCIPvarGetPseudoSol(var);
171 
173  return SCIP_UNKNOWN;
174 
175  default:
176  SCIPerrorMessage("unknown solution origin <%d>\n", sol->solorigin);
177  SCIPABORT();
178  return 0.0; /*lint !e527*/
179  }
180  }
181 }
182 
183 /** stores solution value of variable in solution's own array */
184 static
186  SCIP_SOL* sol, /**< primal CIP solution */
187  SCIP_SET* set, /**< global SCIP settings */
188  SCIP_VAR* var /**< problem variable */
189  )
190 {
191  SCIP_Real solval;
192 
193  assert(sol != NULL);
194  assert(var != NULL);
195  assert(SCIPvarIsTransformed(var));
197 
198  /* if variable is already valid, nothing has to be done */
199  if( SCIPboolarrayGetVal(sol->valid, SCIPvarGetIndex(var)) )
200  return SCIP_OKAY;
201 
202  SCIPdebugMessage("unlinking solution value of variable <%s>\n", SCIPvarGetName(var));
203 
204  /* store the correct solution value into the solution array */
205  switch( sol->solorigin )
206  {
208  SCIPerrorMessage("cannot unlink solutions of original problem space\n");
209  return SCIP_INVALIDDATA;
210 
211  case SCIP_SOLORIGIN_ZERO:
212  return SCIP_OKAY;
213 
215  solval = SCIPvarGetLPSol(var);
216  SCIP_CALL( solSetArrayVal(sol, set, var, solval) );
217  return SCIP_OKAY;
218 
220  solval = SCIPvarGetNLPSol(var);
221  SCIP_CALL( solSetArrayVal(sol, set, var, solval) );
222  return SCIP_OKAY;
223 
225  solval = SCIPvarGetRelaxSolTransVar(var);
226  SCIP_CALL( solSetArrayVal(sol, set, var, solval) );
227  return SCIP_OKAY;
228 
230  solval = SCIPvarGetPseudoSol(var);
231  SCIP_CALL( solSetArrayVal(sol, set, var, solval) );
232  return SCIP_OKAY;
233 
235  SCIP_CALL( solSetArrayVal(sol, set, var, SCIP_UNKNOWN) );
236  return SCIP_OKAY;
237 
238  default:
239  SCIPerrorMessage("unknown solution origin <%d>\n", sol->solorigin);
240  return SCIP_INVALIDDATA;
241  }
242 }
243 
244 /** sets the solution time, nodenum, runnum, and depth stamp to the current values */
245 static
246 void solStamp(
247  SCIP_SOL* sol, /**< primal CIP solution */
248  SCIP_STAT* stat, /**< problem statistics data */
249  SCIP_TREE* tree, /**< branch and bound tree, or NULL */
250  SCIP_Bool checktime /**< should the time be updated? */
251  )
252 {
253  assert(sol != NULL);
254  assert(stat != NULL);
255 
256  if( checktime )
257  sol->time = SCIPclockGetTime(stat->solvingtime);
258  else
259  sol->time = SCIPclockGetLastTime(stat->solvingtime);
260  sol->nodenum = stat->nnodes;
261  sol->runnum = stat->nruns;
262  if( tree == NULL )
263  sol->depth = -1;
264  else
265  sol->depth = SCIPtreeGetCurrentDepth(tree);
266 }
267 
268 /** creates primal CIP solution, initialized to zero */
270  SCIP_SOL** sol, /**< pointer to primal CIP solution */
271  BMS_BLKMEM* blkmem, /**< block memory */
272  SCIP_SET* set, /**< global SCIP settings */
273  SCIP_STAT* stat, /**< problem statistics data */
274  SCIP_PRIMAL* primal, /**< primal data */
275  SCIP_TREE* tree, /**< branch and bound tree */
276  SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */
277  )
278 {
279  assert(sol != NULL);
280  assert(blkmem != NULL);
281  assert(stat != NULL);
282 
283  SCIP_ALLOC( BMSallocBlockMemory(blkmem, sol) );
284  SCIP_CALL( SCIPrealarrayCreate(&(*sol)->vals, blkmem) );
285  SCIP_CALL( SCIPboolarrayCreate(&(*sol)->valid, blkmem) );
286  (*sol)->heur = heur;
287  (*sol)->solorigin = SCIP_SOLORIGIN_ZERO;
288  (*sol)->obj = 0.0;
289  (*sol)->primalindex = -1;
290  (*sol)->index = stat->solindex;
291  (*sol)->hasinfval = FALSE;
292  stat->solindex++;
293  solStamp(*sol, stat, tree, TRUE);
294 
295  SCIP_CALL( SCIPprimalSolCreated(primal, set, *sol) );
296 
297  return SCIP_OKAY;
298 }
299 
300 /** creates primal CIP solution in original problem space, initialized to the offset in the original problem */
302  SCIP_SOL** sol, /**< pointer to primal CIP solution */
303  BMS_BLKMEM* blkmem, /**< block memory */
304  SCIP_SET* set, /**< global SCIP settings */
305  SCIP_STAT* stat, /**< problem statistics data */
306  SCIP_PROB* origprob, /**< original problem data */
307  SCIP_PRIMAL* primal, /**< primal data */
308  SCIP_TREE* tree, /**< branch and bound tree */
309  SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */
310  )
311 {
312  assert(sol != NULL);
313  assert(blkmem != NULL);
314  assert(stat != NULL);
315 
316  SCIP_ALLOC( BMSallocBlockMemory(blkmem, sol) );
317  SCIP_CALL( SCIPrealarrayCreate(&(*sol)->vals, blkmem) );
318  SCIP_CALL( SCIPboolarrayCreate(&(*sol)->valid, blkmem) );
319  (*sol)->heur = heur;
320  (*sol)->solorigin = SCIP_SOLORIGIN_ORIGINAL;
321  (*sol)->obj = origprob->objoffset;
322  (*sol)->primalindex = -1;
323  (*sol)->index = stat->solindex;
324  (*sol)->hasinfval = FALSE;
325  stat->solindex++;
326  solStamp(*sol, stat, tree, TRUE);
327 
328  SCIP_CALL( SCIPprimalSolCreated(primal, set, *sol) );
329 
330  return SCIP_OKAY;
331 }
332 
333 /** creates a copy of a primal CIP solution */
335  SCIP_SOL** sol, /**< pointer to store the copy of the primal CIP solution */
336  BMS_BLKMEM* blkmem, /**< block memory */
337  SCIP_SET* set, /**< global SCIP settings */
338  SCIP_STAT* stat, /**< problem statistics data */
339  SCIP_PRIMAL* primal, /**< primal data */
340  SCIP_SOL* sourcesol /**< primal CIP solution to copy */
341  )
342 {
343  assert(sol != NULL);
344  assert(sourcesol != NULL);
345 
346  SCIP_ALLOC( BMSallocBlockMemory(blkmem, sol) );
347  SCIP_CALL( SCIPrealarrayCopy(&(*sol)->vals, blkmem, sourcesol->vals) );
348  SCIP_CALL( SCIPboolarrayCopy(&(*sol)->valid, blkmem, sourcesol->valid) );
349  (*sol)->heur = sourcesol->heur;
350  (*sol)->obj = sourcesol->obj;
351  (*sol)->primalindex = -1;
352  (*sol)->time = sourcesol->time;
353  (*sol)->nodenum = sourcesol->nodenum;
354  (*sol)->solorigin = sourcesol->solorigin;
355  (*sol)->runnum = sourcesol->runnum;
356  (*sol)->depth = sourcesol->depth;
357  (*sol)->index = stat->solindex;
358  (*sol)->hasinfval = sourcesol->hasinfval;
359  stat->solindex++;
360 
361  SCIP_CALL( SCIPprimalSolCreated(primal, set, *sol) );
362 
363  return SCIP_OKAY;
364 }
365 
366 /** transformes given original solution to the transformed space; a corresponding transformed solution has to be given
367  * which is copied into the existing solution and freed afterwards
368  */
370  SCIP_SOL* sol, /**< primal CIP solution to change, living in original space */
371  SCIP_SOL** transsol, /**< pointer to corresponding transformed primal CIP solution */
372  BMS_BLKMEM* blkmem, /**< block memory */
373  SCIP_SET* set, /**< global SCIP settings */
374  SCIP_PRIMAL* primal /**< primal data */
375  )
376 { /*lint --e{715}*/
377  SCIP_REALARRAY* tmpvals;
378  SCIP_BOOLARRAY* tmpvalid;
379  SCIP_SOL* tsol;
380 
381  assert(sol != NULL);
382  assert(transsol != NULL);
383  assert(SCIPsolIsOriginal(sol));
384  assert(sol->primalindex > -1);
385 
386  tsol = *transsol;
387  assert(tsol != NULL);
388  assert(!SCIPsolIsOriginal(tsol));
389 
390  /* switch vals and valid arrays; the exisiting solution gets the arrays of the transformed solution;
391  * the transformed one gets the original arrays, because they have to be freed anyway and freeing the transsol
392  * automatically frees its arrays
393  */
394  tmpvals = sol->vals;
395  tmpvalid = sol->valid;
396  sol->vals = tsol->vals;
397  sol->valid = tsol->valid;
398  tsol->vals = tmpvals;
399  tsol->valid = tmpvalid;
400 
401  /* copy solorigin and objective (should be the same, only to avoid numerical issues);
402  * we keep the other statistics of the original solution, since that was the first time that this solution as found
403  */
404  sol->solorigin = tsol->solorigin;
405  sol->obj = tsol->obj;
406 
407  SCIP_CALL( SCIPsolFree(transsol, blkmem, primal) );
408 
409  return SCIP_OKAY;
410 }
411 
412 /** adjusts solution values of implicit integer variables in handed solution. Solution objective value is not
413  * deteriorated by this method.
414  */
416  SCIP_SOL* sol, /**< primal CIP solution */
417  SCIP_SET* set, /**< global SCIP settings */
418  SCIP_STAT* stat, /**< problem statistics data */
419  SCIP_PROB* prob, /**< either original or transformed problem, depending on sol origin */
420  SCIP_TREE* tree, /**< branch and bound tree */
421  SCIP_Bool uselprows /**< should LP row information be considered for none-objective variables */
422  )
423 {
424  SCIP_VAR** vars;
425  int nimplvars;
426  int nbinvars;
427  int nintvars;
428  int v;
429 
430  assert(sol != NULL);
431  assert(prob != NULL);
432 
433  /* get variable data */
434  vars = SCIPprobGetVars(prob);
435  nbinvars = SCIPprobGetNBinVars(prob);
436  nintvars = SCIPprobGetNIntVars(prob);
437  nimplvars = SCIPprobGetNImplVars(prob);
438 
439  if( nimplvars == 0 )
440  return SCIP_OKAY;
441 
442  /* calculate the last array position of implicit integer variables */
443  nimplvars = nbinvars + nintvars + nimplvars;
444 
445  /* loop over implicit integer variables and round them up or down */
446  for( v = nbinvars + nintvars; v < nimplvars; ++v )
447  {
448  SCIP_VAR* var;
449  SCIP_Real solval;
450  SCIP_Real obj;
451  SCIP_Real newsolval;
452  SCIP_Bool roundup;
453  SCIP_Bool rounddown;
454  int nuplocks;
455  int ndownlocks;
456 
457  var = vars[v];
458 
459  assert( SCIPvarGetType(var) == SCIP_VARTYPE_IMPLINT );
460  solval = SCIPsolGetVal(sol, set, stat, var);
461 
462  /* we do not need to round integral solution values or those of variables which are not column variables */
463  if( SCIPsetIsFeasIntegral(set, solval) || SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
464  continue;
465 
466  nuplocks = SCIPvarGetNLocksUp(var);
467  ndownlocks = SCIPvarGetNLocksDown(var);
468  obj = SCIPvarGetObj(var);
469 
470  roundup = FALSE;
471  rounddown = FALSE;
472 
473  /* in case of a non-zero objective coefficient, there is only one possible rounding direction */
474  if( SCIPsetIsFeasNegative(set, obj) )
475  roundup = TRUE;
476  else if( SCIPsetIsFeasPositive(set, obj) )
477  rounddown = TRUE;
478  else if( uselprows )
479  {
480  /* determine rounding direction based on row violations */
481  SCIP_COL* col;
482  SCIP_ROW** rows;
483  SCIP_Real* vals;
484  int nrows;
485  int r;
486 
487  col = SCIPvarGetCol(var);
488  vals = SCIPcolGetVals(col);
489  rows = SCIPcolGetRows(col);
490  nrows = SCIPcolGetNNonz(col);
491 
492  /* loop over rows and search for equations whose violation can be decreased by rounding */
493  for( r = 0; r < nrows && !(roundup && rounddown); ++r )
494  {
495  SCIP_ROW* row;
496  SCIP_Real activity;
497  SCIP_Real rhs;
498  SCIP_Real lhs;
499 
500  row = rows[r];
501  assert(!SCIPsetIsFeasZero(set, vals[r]));
502 
503  if( SCIProwIsLocal(row) || !SCIProwIsInLP(row) )
504  continue;
505 
506  rhs = SCIProwGetRhs(row);
507  lhs = SCIProwGetLhs(row);
508 
509  if( SCIPsetIsInfinity(set, rhs) || SCIPsetIsInfinity(set, -lhs) )
510  continue;
511 
512  activity = SCIProwGetSolActivity(row, set, stat, sol);
513  if( SCIPsetIsFeasLE(set, activity, rhs) && SCIPsetIsFeasLE(set, lhs, activity) )
514  continue;
515 
516  if( (SCIPsetIsFeasGT(set, activity, rhs) && SCIPsetIsPositive(set, vals[r]))
517  || (SCIPsetIsFeasLT(set, activity, lhs) && SCIPsetIsNegative(set, vals[r])) )
518  rounddown = TRUE;
519  else
520  roundup = TRUE;
521  }
522  }
523 
524  /* in case of a tie, we select the rounding step based on the number of variable locks */
525  if( roundup == rounddown )
526  {
527  rounddown = ndownlocks <= nuplocks;
528  roundup = !rounddown;
529  }
530 
531  /* round the variable up or down */
532  if( roundup )
533  {
534  newsolval = SCIPsetCeil(set, solval);
535  assert(SCIPsetIsFeasLE(set, newsolval, SCIPvarGetUbGlobal(var)));
536  }
537  else
538  {
539  assert( rounddown ); /* should be true because of the code above */
540  newsolval = SCIPsetFloor(set, solval);
541  assert(SCIPsetIsFeasGE(set, newsolval, SCIPvarGetLbGlobal(var)));
542  }
543 
544  SCIP_CALL( SCIPsolSetVal(sol, set, stat, tree, var, newsolval) );
545  }
546 
547  return SCIP_OKAY;
548 }
549 /** creates primal CIP solution, initialized to the current LP solution */
551  SCIP_SOL** sol, /**< pointer to primal CIP solution */
552  BMS_BLKMEM* blkmem, /**< block memory */
553  SCIP_SET* set, /**< global SCIP settings */
554  SCIP_STAT* stat, /**< problem statistics data */
555  SCIP_PROB* prob, /**< transformed problem data */
556  SCIP_PRIMAL* primal, /**< primal data */
557  SCIP_TREE* tree, /**< branch and bound tree */
558  SCIP_LP* lp, /**< current LP data */
559  SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */
560  )
561 {
562  assert(sol != NULL);
563  assert(lp != NULL);
564  assert(SCIPlpIsSolved(lp));
565 
566  SCIP_CALL( SCIPsolCreate(sol, blkmem, set, stat, primal, tree, heur) );
567  SCIP_CALL( SCIPsolLinkLPSol(*sol, set, stat, prob, tree, lp) );
568 
569  return SCIP_OKAY;
570 }
571 
572 /** creates primal CIP solution, initialized to the current NLP solution */
574  SCIP_SOL** sol, /**< pointer to primal CIP solution */
575  BMS_BLKMEM* blkmem, /**< block memory */
576  SCIP_SET* set, /**< global SCIP settings */
577  SCIP_STAT* stat, /**< problem statistics data */
578  SCIP_PRIMAL* primal, /**< primal data */
579  SCIP_TREE* tree, /**< branch and bound tree */
580  SCIP_NLP* nlp, /**< current NLP data */
581  SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */
582  )
583 {
584  assert(sol != NULL);
585  assert(nlp != NULL);
586 
587  SCIP_CALL( SCIPsolCreate(sol, blkmem, set, stat, primal, tree, heur) );
588  SCIP_CALL( SCIPsolLinkNLPSol(*sol, stat, tree, nlp) );
589 
590  return SCIP_OKAY;
591 }
592 
593 /** creates primal CIP solution, initialized to the current relaxation solution */
595  SCIP_SOL** sol, /**< pointer to primal CIP solution */
596  BMS_BLKMEM* blkmem, /**< block memory */
597  SCIP_SET* set, /**< global SCIP settings */
598  SCIP_STAT* stat, /**< problem statistics data */
599  SCIP_PRIMAL* primal, /**< primal data */
600  SCIP_TREE* tree, /**< branch and bound tree */
601  SCIP_RELAXATION* relaxation, /**< global relaxation data */
602  SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */
603  )
604 {
605  assert(sol != NULL);
606  assert(relaxation != NULL);
607  assert(SCIPrelaxationIsSolValid(relaxation));
608 
609  SCIP_CALL( SCIPsolCreate(sol, blkmem, set, stat, primal, tree, heur) );
610  SCIP_CALL( SCIPsolLinkRelaxSol(*sol, set, stat, tree, relaxation) );
611 
612  return SCIP_OKAY;
613 }
614 
615 /** creates primal CIP solution, initialized to the current pseudo solution */
617  SCIP_SOL** sol, /**< pointer to primal CIP solution */
618  BMS_BLKMEM* blkmem, /**< block memory */
619  SCIP_SET* set, /**< global SCIP settings */
620  SCIP_STAT* stat, /**< problem statistics data */
621  SCIP_PROB* prob, /**< transformed problem data */
622  SCIP_PRIMAL* primal, /**< primal data */
623  SCIP_TREE* tree, /**< branch and bound tree, or NULL */
624  SCIP_LP* lp, /**< current LP data */
625  SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */
626  )
627 {
628  assert(sol != NULL);
629 
630  SCIP_CALL( SCIPsolCreate(sol, blkmem, set, stat, primal, tree, heur) );
631  SCIP_CALL( SCIPsolLinkPseudoSol(*sol, set, stat, prob, tree, lp) );
632 
633  return SCIP_OKAY;
634 }
635 
636 /** creates primal CIP solution, initialized to the current solution */
638  SCIP_SOL** sol, /**< pointer to primal CIP solution */
639  BMS_BLKMEM* blkmem, /**< block memory */
640  SCIP_SET* set, /**< global SCIP settings */
641  SCIP_STAT* stat, /**< problem statistics data */
642  SCIP_PROB* prob, /**< transformed problem data */
643  SCIP_PRIMAL* primal, /**< primal data */
644  SCIP_TREE* tree, /**< branch and bound tree */
645  SCIP_LP* lp, /**< current LP data */
646  SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */
647  )
648 {
649  assert(tree != NULL);
650 
651  if( SCIPtreeHasCurrentNodeLP(tree) )
652  {
653  SCIP_CALL( SCIPsolCreateLPSol(sol, blkmem, set, stat, prob, primal, tree, lp, heur) );
654  }
655  else
656  {
657  SCIP_CALL( SCIPsolCreatePseudoSol(sol, blkmem, set, stat, prob, primal, tree, lp, heur) );
658  }
659 
660  return SCIP_OKAY;
661 }
662 
663 /** creates primal CIP solution, initialized to unknown values */
665  SCIP_SOL** sol, /**< pointer to primal CIP solution */
666  BMS_BLKMEM* blkmem, /**< block memory */
667  SCIP_SET* set, /**< global SCIP settings */
668  SCIP_STAT* stat, /**< problem statistics data */
669  SCIP_PRIMAL* primal, /**< primal data */
670  SCIP_TREE* tree, /**< branch and bound tree */
671  SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */
672  )
673 {
674  assert(sol != NULL);
675  assert(blkmem != NULL);
676  assert(stat != NULL);
677 
678  SCIP_ALLOC( BMSallocBlockMemory(blkmem, sol) );
679  SCIP_CALL( SCIPrealarrayCreate(&(*sol)->vals, blkmem) );
680  SCIP_CALL( SCIPboolarrayCreate(&(*sol)->valid, blkmem) );
681  (*sol)->heur = heur;
682  (*sol)->solorigin = SCIP_SOLORIGIN_UNKNOWN;
683  (*sol)->obj = 0.0;
684  (*sol)->primalindex = -1;
685  (*sol)->index = stat->solindex;
686  (*sol)->hasinfval = FALSE;
687  stat->solindex++;
688  solStamp(*sol, stat, tree, TRUE);
689 
690  SCIP_CALL( SCIPprimalSolCreated(primal, set, *sol) );
691 
692  return SCIP_OKAY;
693 }
694 
695 /** frees primal CIP solution */
697  SCIP_SOL** sol, /**< pointer to primal CIP solution */
698  BMS_BLKMEM* blkmem, /**< block memory */
699  SCIP_PRIMAL* primal /**< primal data */
700  )
701 {
702  assert(sol != NULL);
703  assert(*sol != NULL);
704 
705  SCIPprimalSolFreed(primal, *sol);
706 
707  SCIP_CALL( SCIPrealarrayFree(&(*sol)->vals) );
708  SCIP_CALL( SCIPboolarrayFree(&(*sol)->valid) );
709  BMSfreeBlockMemory(blkmem, sol);
710 
711  return SCIP_OKAY;
712 }
713 
714 /** copies current LP solution into CIP solution by linking */
716  SCIP_SOL* sol, /**< primal CIP solution */
717  SCIP_SET* set, /**< global SCIP settings */
718  SCIP_STAT* stat, /**< problem statistics data */
719  SCIP_PROB* prob, /**< transformed problem data */
720  SCIP_TREE* tree, /**< branch and bound tree */
721  SCIP_LP* lp /**< current LP data */
722  )
723 {
724  assert(sol != NULL);
725  assert(stat != NULL);
726  assert(tree != NULL);
727  assert(lp != NULL);
728  assert(lp->solved);
729  assert(SCIPlpDiving(lp) || !SCIPlpDivingObjChanged(lp));
730 
731  SCIPdebugMessage("linking solution to LP\n");
732 
733  /* clear the old solution arrays */
734  SCIP_CALL( solClearArrays(sol) );
735 
736  /* link solution to LP solution */
737  if( SCIPlpDivingObjChanged(lp) )
738  {
739  /* the objective value has to be calculated manually, because the LP's value is invalid;
740  * use objective values of variables, because columns objective values are changed to dive values
741  */
742  sol->obj = SCIPlpGetLooseObjval(lp, set, prob);
743  if( !SCIPsetIsInfinity(set, -sol->obj) )
744  {
745  SCIP_VAR* var;
746  SCIP_COL** cols;
747  int ncols;
748  int c;
749 
750  cols = SCIPlpGetCols(lp);
751  ncols = SCIPlpGetNCols(lp);
752  for( c = 0; c < ncols; ++c )
753  {
754  var = SCIPcolGetVar(cols[c]);
755  sol->obj += SCIPvarGetObj(var) * cols[c]->primsol;
756  }
757  }
758  }
759  else
760  {
761  /* the objective value in the columns is correct, s.t. the LP's objective value is also correct */
762  sol->obj = SCIPlpGetObjval(lp, set, prob);
763  }
765  solStamp(sol, stat, tree, TRUE);
766 
767  SCIPdebugMessage(" -> objective value: %g\n", sol->obj);
768 
769  return SCIP_OKAY;
770 }
771 
772 /** copies current NLP solution into CIP solution by linking */
774  SCIP_SOL* sol, /**< primal CIP solution */
775  SCIP_STAT* stat, /**< problem statistics data */
776  SCIP_TREE* tree, /**< branch and bound tree */
777  SCIP_NLP* nlp /**< current NLP data */
778  )
779 {
780  assert(sol != NULL);
781  assert(stat != NULL);
782  assert(tree != NULL);
783  assert(nlp != NULL);
785 
786  SCIPdebugMessage("linking solution to NLP\n");
787 
788  /* clear the old solution arrays */
789  SCIP_CALL( solClearArrays(sol) );
790 
791  /* get objective value of NLP solution */
792  if( SCIPnlpIsDivingObjChanged(nlp) )
793  {
794  /* the objective value has to be calculated manually, because the NLP's value is invalid */
795 
796  SCIP_VAR** vars;
797  int nvars;
798  int v;
799 
800  sol->obj = 0.0;
801 
802  vars = SCIPnlpGetVars(nlp);
803  nvars = SCIPnlpGetNVars(nlp);
804  for( v = 0; v < nvars; ++v )
805  {
806  assert(SCIPvarIsActive(vars[v]));
807  sol->obj += SCIPvarGetObj(vars[v]) * SCIPvarGetNLPSol(vars[v]);
808  }
809  }
810  else
811  {
812  sol->obj = SCIPnlpGetObjval(nlp);
813  }
814 
816  solStamp(sol, stat, tree, TRUE);
817 
818  SCIPdebugMessage(" -> objective value: %g\n", sol->obj);
819 
820  return SCIP_OKAY;
821 }
822 
823 /** copies current relaxation solution into CIP solution by linking */
825  SCIP_SOL* sol, /**< primal CIP solution */
826  SCIP_SET* set, /**< global SCIP settings */
827  SCIP_STAT* stat, /**< problem statistics data */
828  SCIP_TREE* tree, /**< branch and bound tree */
829  SCIP_RELAXATION* relaxation /**< global relaxation data */
830  )
831 { /*lint --e{715}*/
832  assert(sol != NULL);
833  assert(stat != NULL);
834  assert(tree != NULL);
835  assert(relaxation != NULL);
836  assert(SCIPrelaxationIsSolValid(relaxation));
837 
838  SCIPdebugMessage("linking solution to relaxation\n");
839 
840  /* clear the old solution arrays */
841  SCIP_CALL( solClearArrays(sol) );
842 
843  /* the objective value in the columns is correct, s.t. the LP's objective value is also correct */
844  sol->obj = SCIPrelaxationGetSolObj(relaxation);
846  solStamp(sol, stat, tree, TRUE);
847 
848  SCIPdebugMessage(" -> objective value: %g\n", sol->obj);
849 
850  return SCIP_OKAY;
851 }
852 
853 /** copies current pseudo solution into CIP solution by linking */
855  SCIP_SOL* sol, /**< primal CIP solution */
856  SCIP_SET* set, /**< global SCIP settings */
857  SCIP_STAT* stat, /**< problem statistics data */
858  SCIP_PROB* prob, /**< transformed problem data */
859  SCIP_TREE* tree, /**< branch and bound tree, or NULL */
860  SCIP_LP* lp /**< current LP data */
861  )
862 {
863  assert(sol != NULL);
864  assert(stat != NULL);
865  assert(tree != NULL);
866 
867  SCIPdebugMessage("linking solution to pseudo solution\n");
868 
869  /* clear the old solution arrays */
870  SCIP_CALL( solClearArrays(sol) );
871 
872  /* link solution to pseudo solution */
873  sol->obj = SCIPlpGetPseudoObjval(lp, set, prob);
875  solStamp(sol, stat, tree, TRUE);
876 
877  SCIPdebugMessage(" -> objective value: %g\n", sol->obj);
878 
879  return SCIP_OKAY;
880 }
881 
882 /** copies current solution (LP or pseudo solution) into CIP solution by linking */
884  SCIP_SOL* sol, /**< primal CIP solution */
885  SCIP_SET* set, /**< global SCIP settings */
886  SCIP_STAT* stat, /**< problem statistics data */
887  SCIP_PROB* prob, /**< transformed problem data */
888  SCIP_TREE* tree, /**< branch and bound tree */
889  SCIP_LP* lp /**< current LP data */
890  )
891 {
892  assert(tree != NULL);
893 
894  SCIPdebugMessage("linking solution to current solution\n");
895 
896  if( SCIPtreeHasCurrentNodeLP(tree) && SCIPlpIsSolved(lp) )
897  {
898  SCIP_CALL( SCIPsolLinkLPSol(sol, set, stat, prob, tree, lp) );
899  }
900  else
901  {
902  SCIP_CALL( SCIPsolLinkPseudoSol(sol, set, stat, prob, tree, lp) );
903  }
904 
905  return SCIP_OKAY;
906 }
907 
908 /** clears primal CIP solution */
910  SCIP_SOL* sol, /**< primal CIP solution */
911  SCIP_STAT* stat, /**< problem statistics data */
912  SCIP_TREE* tree /**< branch and bound tree */
913  )
914 {
915  assert(sol != NULL);
916 
917  SCIP_CALL( solClearArrays(sol) );
919  sol->obj = 0.0;
920  solStamp(sol, stat, tree, TRUE);
921 
922  return SCIP_OKAY;
923 }
924 
925 /** declares all entries in the primal CIP solution to be unknown */
927  SCIP_SOL* sol, /**< primal CIP solution */
928  SCIP_STAT* stat, /**< problem statistics data */
929  SCIP_TREE* tree /**< branch and bound tree */
930  )
931 {
932  assert(sol != NULL);
933 
934  SCIP_CALL( solClearArrays(sol) );
936  sol->obj = 0.0;
937  solStamp(sol, stat, tree, TRUE);
938 
939  return SCIP_OKAY;
940 }
941 
942 /** stores solution values of variables in solution's own array */
944  SCIP_SOL* sol, /**< primal CIP solution */
945  SCIP_SET* set, /**< global SCIP settings */
946  SCIP_PROB* prob /**< transformed problem data */
947  )
948 {
949  int v;
950 
951  assert(sol != NULL);
952  assert(prob != NULL);
953  assert(prob->nvars == 0 || prob->vars != NULL);
954 
955  if( !SCIPsolIsOriginal(sol) && sol->solorigin != SCIP_SOLORIGIN_ZERO
956  && sol->solorigin != SCIP_SOLORIGIN_UNKNOWN )
957  {
958  SCIPdebugMessage("completing solution %p\n", (void*)sol);
959 
960  for( v = 0; v < prob->nvars; ++v )
961  {
962  SCIP_CALL( solUnlinkVar(sol, set, prob->vars[v]) );
963  }
964 
966  }
967 
968  return SCIP_OKAY;
969 }
970 
971 /** sets value of variable in primal CIP solution */
973  SCIP_SOL* sol, /**< primal CIP solution */
974  SCIP_SET* set, /**< global SCIP settings */
975  SCIP_STAT* stat, /**< problem statistics data */
976  SCIP_TREE* tree, /**< branch and bound tree, or NULL */
977  SCIP_VAR* var, /**< variable to add to solution */
978  SCIP_Real val /**< solution value of variable */
979  )
980 {
981  SCIP_Real oldval;
982 
983  assert(sol != NULL);
984  assert(sol->solorigin == SCIP_SOLORIGIN_ORIGINAL
985  || sol->solorigin == SCIP_SOLORIGIN_ZERO
987  || (sol->nodenum == stat->nnodes && sol->runnum == stat->nruns));
988  assert(stat != NULL);
989  assert(var != NULL);
990 
991  SCIPdebugMessage("setting value of <%s> in solution %p to %g\n", SCIPvarGetName(var), (void*)sol, val);
992 
993  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
994  switch( SCIPvarGetStatus(var) )
995  {
997  if( SCIPsolIsOriginal(sol) )
998  {
999  oldval = solGetArrayVal(sol, var);
1000  if( !SCIPsetIsEQ(set, val, oldval) )
1001  {
1002  SCIP_Real obj;
1003 
1004  SCIP_CALL( solSetArrayVal(sol, set, var, val) );
1005 
1006  /* update objective: an unknown solution value does not count towards the objective */
1007  obj = SCIPvarGetObj(var);
1008  if( oldval != SCIP_UNKNOWN ) /*lint !e777*/
1009  sol->obj -= obj * oldval;
1010  if( val != SCIP_UNKNOWN ) /*lint !e777*/
1011  sol->obj += obj * val;
1012 
1013  solStamp(sol, stat, tree, FALSE);
1014 
1015  }
1016  return SCIP_OKAY;
1017  }
1018  else
1019  return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetTransVar(var), val);
1020 
1021  case SCIP_VARSTATUS_LOOSE:
1022  case SCIP_VARSTATUS_COLUMN:
1023  assert(!SCIPsolIsOriginal(sol));
1024  oldval = solGetArrayVal(sol, var);
1025  if( !SCIPsetIsEQ(set, val, oldval) )
1026  {
1027  SCIP_Real obj;
1028 
1029  SCIP_CALL( solSetArrayVal(sol, set, var, val) );
1030 
1031  /* update objective: an unknown solution value does not count towards the objective */
1032  obj = SCIPvarGetObj(var);
1033  if( oldval != SCIP_UNKNOWN ) /*lint !e777*/
1034  sol->obj -= obj * oldval;
1035  if( val != SCIP_UNKNOWN ) /*lint !e777*/
1036  sol->obj += obj * val;
1037 
1038  solStamp(sol, stat, tree, FALSE);
1039  }
1040  return SCIP_OKAY;
1041 
1042  case SCIP_VARSTATUS_FIXED:
1043  assert(!SCIPsolIsOriginal(sol));
1044  oldval = SCIPvarGetLbGlobal(var);
1045  if( !SCIPsetIsEQ(set, val, oldval) )
1046  {
1047  SCIPerrorMessage("cannot set solution value for variable <%s> fixed to %.15g to different value %.15g\n",
1048  SCIPvarGetName(var), oldval, val);
1049  return SCIP_INVALIDDATA;
1050  }
1051  return SCIP_OKAY;
1052 
1053  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
1054  assert(!SCIPsetIsZero(set, SCIPvarGetAggrScalar(var)));
1057 
1058  if( val == SCIP_UNKNOWN )/*lint !e777*/
1059  return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetAggrVar(var), val);
1060  if( SCIPsetIsInfinity(set, val) || SCIPsetIsInfinity(set, -val) )
1061  return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetAggrVar(var), SCIPvarGetAggrScalar(var) > 0 ? val : -val);
1062  else
1063  return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetAggrVar(var), (val - SCIPvarGetAggrConstant(var))/SCIPvarGetAggrScalar(var));
1064 
1066  if ( SCIPvarGetMultaggrNVars(var) == 1 )
1067  {
1068  SCIP_VAR** multaggrvars;
1069  SCIP_Real* multaggrscalars;
1070  SCIP_Real multaggrconstant;
1071 
1072  multaggrvars = SCIPvarGetMultaggrVars(var);
1073  multaggrscalars = SCIPvarGetMultaggrScalars(var);
1074  multaggrconstant = SCIPvarGetMultaggrConstant(var);
1075 
1076  if( SCIPsetIsInfinity(set, multaggrconstant) || SCIPsetIsInfinity(set, -multaggrconstant) )
1077  {
1078  if( (SCIPsetIsInfinity(set, multaggrconstant) && !SCIPsetIsInfinity(set, val))
1079  || (SCIPsetIsInfinity(set, -multaggrconstant) && !SCIPsetIsInfinity(set, -val)) )
1080  {
1081  SCIPerrorMessage("cannot set solution value for variable <%s> fixed to %.15g to different value %.15g\n",
1082  SCIPvarGetName(var), multaggrconstant, val);
1083  return SCIP_INVALIDDATA;
1084  }
1085  return SCIP_OKAY;
1086  }
1087  else
1088  {
1089  if( SCIPsetIsInfinity(set, val) || SCIPsetIsInfinity(set, -val) )
1090  return SCIPsolSetVal(sol, set, stat, tree, multaggrvars[0], multaggrscalars[0] > 0 ? val : -val);
1091  else
1092  return SCIPsolSetVal(sol, set, stat, tree, multaggrvars[0], (val - multaggrconstant)/multaggrscalars[0]);
1093  }
1094  }
1095  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
1096  return SCIP_INVALIDDATA;
1097 
1100 
1101  if( val == SCIP_UNKNOWN )/*lint !e777*/
1102  return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetNegationVar(var), val);
1103  else if( SCIPsetIsInfinity(set, val) || SCIPsetIsInfinity(set, -val) )
1104  return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetNegationVar(var), -val);
1105  else
1106  return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetNegationVar(var), SCIPvarGetNegationConstant(var) - val);
1107 
1108  default:
1109  SCIPerrorMessage("unknown variable status\n");
1110  return SCIP_INVALIDDATA;
1111  }
1112 }
1113 
1114 /** increases value of variable in primal CIP solution */
1116  SCIP_SOL* sol, /**< primal CIP solution */
1117  SCIP_SET* set, /**< global SCIP settings */
1118  SCIP_STAT* stat, /**< problem statistics data */
1119  SCIP_TREE* tree, /**< branch and bound tree */
1120  SCIP_VAR* var, /**< variable to increase solution value for */
1121  SCIP_Real incval /**< increment for solution value of variable */
1122  )
1123 {
1124  SCIP_Real oldval;
1125 
1126  assert(sol != NULL);
1127  assert(sol->solorigin == SCIP_SOLORIGIN_ORIGINAL
1128  || sol->solorigin == SCIP_SOLORIGIN_ZERO
1129  || (sol->nodenum == stat->nnodes && sol->runnum == stat->nruns));
1130  assert(stat != NULL);
1131  assert(var != NULL);
1132  assert(!SCIPsetIsInfinity(set, incval) && !SCIPsetIsInfinity(set, -incval));
1133 
1134  SCIPdebugMessage("increasing value of <%s> in solution %p by %g\n", SCIPvarGetName(var), (void*)sol, incval);
1135 
1136  if( SCIPsetIsZero(set, incval) )
1137  return SCIP_OKAY;
1138 
1139  oldval = solGetArrayVal(sol, var);
1140  if( SCIPsetIsInfinity(set, oldval) || SCIPsetIsInfinity(set, -oldval) )
1141  return SCIP_OKAY;
1142 
1143  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
1144  /* @todo: handle strange cases, such as sums that yield infinite values */
1145  switch( SCIPvarGetStatus(var) )
1146  {
1148  if( SCIPsolIsOriginal(sol) )
1149  {
1150  SCIP_CALL( solIncArrayVal(sol, set, var, incval) );
1151  sol->obj += SCIPvarGetObj(var) * incval;
1152  solStamp(sol, stat, tree, FALSE);
1153  return SCIP_OKAY;
1154  }
1155  else
1156  return SCIPsolIncVal(sol, set, stat, tree, SCIPvarGetTransVar(var), incval);
1157 
1158  case SCIP_VARSTATUS_LOOSE:
1159  case SCIP_VARSTATUS_COLUMN:
1160  assert(!SCIPsolIsOriginal(sol));
1161  SCIP_CALL( solIncArrayVal(sol, set, var, incval) );
1162  sol->obj += SCIPvarGetObj(var) * incval;
1163  solStamp(sol, stat, tree, FALSE);
1164  return SCIP_OKAY;
1165 
1166  case SCIP_VARSTATUS_FIXED:
1167  SCIPerrorMessage("cannot increase solution value for fixed variable\n");
1168  return SCIP_INVALIDDATA;
1169 
1170  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
1171  assert(!SCIPsetIsZero(set, SCIPvarGetAggrScalar(var)));
1172  return SCIPsolIncVal(sol, set, stat, tree, SCIPvarGetAggrVar(var), incval/SCIPvarGetAggrScalar(var));
1173 
1175  SCIPerrorMessage("cannot increase solution value for multiple aggregated variable\n");
1176  return SCIP_INVALIDDATA;
1177 
1179  return SCIPsolIncVal(sol, set, stat, tree, SCIPvarGetNegationVar(var), -incval);
1180 
1181  default:
1182  SCIPerrorMessage("unknown variable status\n");
1183  return SCIP_INVALIDDATA;
1184  }
1185 }
1186 
1187 /** returns value of variable in primal CIP solution */
1189  SCIP_SOL* sol, /**< primal CIP solution */
1190  SCIP_SET* set, /**< global SCIP settings */
1191  SCIP_STAT* stat, /**< problem statistics data */
1192  SCIP_VAR* var /**< variable to get value for */
1193  )
1194 {
1195  SCIP_VAR** vars;
1196  SCIP_Real* scalars;
1197  SCIP_Real solval;
1198  SCIP_Real solvalsum;
1199  int nvars;
1200  int i;
1201 
1202  assert(sol != NULL);
1203  assert(sol->solorigin == SCIP_SOLORIGIN_ORIGINAL
1204  || sol->solorigin == SCIP_SOLORIGIN_ZERO
1206  || (sol->nodenum == stat->nnodes && sol->runnum == stat->nruns));
1207  assert(var != NULL);
1208 
1209  /* if the value of a transformed variable in an original solution is requested, we need to project the variable back
1210  * to the original space, the opposite case is handled below
1211  */
1212  if( SCIPsolIsOriginal(sol) && SCIPvarIsTransformed(var) )
1213  {
1214  SCIP_RETCODE retcode;
1215  SCIP_VAR* origvar;
1216  SCIP_Real scalar;
1217  SCIP_Real constant;
1218 
1219  /* we cannot get the value of a transformed variable for a solution that lives in the original problem space
1220  * -> get the corresponding original variable first
1221  */
1222  origvar = var;
1223  scalar = 1.0;
1224  constant = 0.0;
1225  retcode = SCIPvarGetOrigvarSum(&origvar, &scalar, &constant);
1226  if ( retcode != SCIP_OKAY )
1227  return SCIP_INVALID;
1228  if( origvar == NULL )
1229  {
1230  /* the variable has no original counterpart: in the original solution, it has a value of zero */
1231  return 0.0;
1232  }
1233  assert(!SCIPvarIsTransformed(origvar));
1234  return scalar * SCIPsolGetVal(sol, set, stat, origvar) + constant;
1235  }
1236 
1237  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
1238  switch( SCIPvarGetStatus(var) )
1239  {
1241  if( SCIPsolIsOriginal(sol) )
1242  return solGetArrayVal(sol, var);
1243  else
1244  return SCIPsolGetVal(sol, set, stat, SCIPvarGetTransVar(var));
1245 
1246  case SCIP_VARSTATUS_LOOSE:
1247  case SCIP_VARSTATUS_COLUMN:
1248  assert(!SCIPsolIsOriginal(sol));
1249  return solGetArrayVal(sol, var);
1250 
1251  case SCIP_VARSTATUS_FIXED:
1252  assert(!SCIPsolIsOriginal(sol));
1253  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
1254  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
1255  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
1256  return SCIPvarGetLbGlobal(var);
1257 
1258  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
1259  solval = SCIPsolGetVal(sol, set, stat, SCIPvarGetAggrVar(var));
1260  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1261  return SCIP_UNKNOWN;
1262  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
1263  {
1264  if( SCIPvarGetAggrScalar(var) * solval > 0.0 )
1265  return SCIPsetInfinity(set);
1266  if( SCIPvarGetAggrScalar(var) * solval < 0.0 )
1267  return -SCIPsetInfinity(set);
1268  }
1269  return SCIPvarGetAggrScalar(var) * solval + SCIPvarGetAggrConstant(var);
1270 
1272  nvars = SCIPvarGetMultaggrNVars(var);
1273  vars = SCIPvarGetMultaggrVars(var);
1274  scalars = SCIPvarGetMultaggrScalars(var);
1275  solvalsum = SCIPvarGetMultaggrConstant(var);
1276  for( i = 0; i < nvars; ++i )
1277  {
1278  solval = SCIPsolGetVal(sol, set, stat, vars[i]);
1279  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1280  return SCIP_UNKNOWN;
1281  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
1282  {
1283  if( scalars[i] * solval > 0.0 )
1284  return SCIPsetInfinity(set);
1285  if( scalars[i] * solval < 0.0 )
1286  return -SCIPsetInfinity(set);
1287  }
1288  solvalsum += scalars[i] * solval;
1289  }
1290  return solvalsum;
1291 
1293  solval = SCIPsolGetVal(sol, set, stat, SCIPvarGetNegationVar(var));
1294  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1295  return SCIP_UNKNOWN;
1296  if( SCIPsetIsInfinity(set, solval) )
1297  return -SCIPsetInfinity(set);
1298  if( SCIPsetIsInfinity(set, -solval) )
1299  return SCIPsetInfinity(set);
1300  return SCIPvarGetNegationConstant(var) - solval;
1301 
1302  default:
1303  SCIPerrorMessage("unknown variable status\n");
1304  SCIPABORT();
1305  return 0.0; /*lint !e527*/
1306  }
1307 }
1308 
1309 /** returns value of variable in primal ray represented by primal CIP solution */
1311  SCIP_SOL* sol, /**< primal CIP solution, representing a primal ray */
1312  SCIP_SET* set, /**< global SCIP settings */
1313  SCIP_STAT* stat, /**< problem statistics data */
1314  SCIP_VAR* var /**< variable to get value for */
1315  )
1316 {
1317  SCIP_VAR** vars;
1318  SCIP_Real* scalars;
1319  SCIP_Real solval;
1320  SCIP_Real solvalsum;
1321  int nvars;
1322  int i;
1323 
1324  assert(sol != NULL);
1325  assert(sol->solorigin == SCIP_SOLORIGIN_ZERO);
1326  assert(var != NULL);
1327 
1328  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
1329  switch( SCIPvarGetStatus(var) )
1330  {
1332  return SCIPsolGetRayVal(sol, set, stat, SCIPvarGetTransVar(var));
1333 
1334  case SCIP_VARSTATUS_LOOSE:
1335  case SCIP_VARSTATUS_COLUMN:
1336  return solGetArrayVal(sol, var);
1337 
1338  case SCIP_VARSTATUS_FIXED:
1339  assert(!SCIPsolIsOriginal(sol));
1340  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
1341  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
1342  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
1343  return 0.0; /* constants are ignored for computing the ray direction */
1344 
1345  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
1346  solval = SCIPsolGetRayVal(sol, set, stat, SCIPvarGetAggrVar(var));
1347  assert(solval != SCIP_UNKNOWN); /*lint !e777*/
1348  assert(!SCIPsetIsInfinity(set, REALABS(solval)));
1349  return SCIPvarGetAggrScalar(var) * solval; /* constants are ignored for computing the ray direction */
1350 
1352  nvars = SCIPvarGetMultaggrNVars(var);
1353  vars = SCIPvarGetMultaggrVars(var);
1354  scalars = SCIPvarGetMultaggrScalars(var);
1355  solvalsum = 0.0; /* constants are ignored for computing the ray direction */
1356  for( i = 0; i < nvars; ++i )
1357  {
1358  solval = SCIPsolGetRayVal(sol, set, stat, vars[i]);
1359  assert(solval != SCIP_UNKNOWN ); /*lint !e777*/
1360  assert(!SCIPsetIsInfinity(set, REALABS(solval)));
1361  solvalsum += scalars[i] * solval;
1362  }
1363  return solvalsum;
1364 
1366  solval = SCIPsolGetRayVal(sol, set, stat, SCIPvarGetNegationVar(var));
1367  assert(solval != SCIP_UNKNOWN); /*lint !e777*/
1368  assert(!SCIPsetIsInfinity(set, REALABS(solval)));
1369  return -solval; /* constants are ignored for computing the ray direction */
1370 
1371  default:
1372  SCIPerrorMessage("unknown variable status\n");
1373  SCIPABORT();
1374  return 0.0; /*lint !e527*/
1375  }
1376 }
1377 
1378 /** gets objective value of primal CIP solution in transformed problem */
1380  SCIP_SOL* sol, /**< primal CIP solution */
1381  SCIP_SET* set, /**< global SCIP settings */
1382  SCIP_PROB* transprob, /**< tranformed problem data */
1383  SCIP_PROB* origprob /**< original problem data */
1384  )
1385 {
1386  assert(sol != NULL);
1387 
1388  /* for original solutions, sol->obj contains the external objective value */
1389  if( SCIPsolIsOriginal(sol) )
1390  return SCIPprobInternObjval(transprob, origprob, set, sol->obj);
1391  else
1392  return sol->obj;
1393 }
1394 
1395 /** updates primal solutions after a change in a variable's objective value */
1397  SCIP_SOL* sol, /**< primal CIP solution */
1398  SCIP_VAR* var, /**< problem variable */
1399  SCIP_Real oldobj, /**< old objective value */
1400  SCIP_Real newobj /**< new objective value */
1401  )
1402 {
1403  SCIP_Real solval;
1404 
1405  assert(sol != NULL);
1406  assert(!SCIPsolIsOriginal(sol));
1408 
1409  solval = solGetArrayVal(sol, var);
1410  if( solval != SCIP_UNKNOWN ) /*lint !e777*/
1411  sol->obj += (newobj - oldobj) * solval;
1412 }
1413 
1414 /** checks primal CIP solution for feasibility */
1416  SCIP_SOL* sol, /**< primal CIP solution */
1417  SCIP_SET* set, /**< global SCIP settings */
1418  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1419  BMS_BLKMEM* blkmem, /**< block memory */
1420  SCIP_STAT* stat, /**< problem statistics */
1421  SCIP_PROB* prob, /**< transformed problem data */
1422  SCIP_Bool printreason, /**< should all reasons of violations be printed? */
1423  SCIP_Bool checkbounds, /**< should the bounds of the variables be checked? */
1424  SCIP_Bool checkintegrality, /**< has integrality to be checked? */
1425  SCIP_Bool checklprows, /**< have current LP rows to be checked? */
1426  SCIP_Bool* feasible /**< stores whether solution is feasible */
1427  )
1428 {
1429  SCIP_RESULT result;
1430  int h;
1431 
1432  assert(sol != NULL);
1433  assert(!SCIPsolIsOriginal(sol));
1434  assert(set != NULL);
1435  assert(prob != NULL);
1436  assert(feasible != NULL);
1437 
1438  SCIPdebugMessage("checking solution with objective value %g (nodenum=%"SCIP_LONGINT_FORMAT", origin=%u)\n",
1439  sol->obj, sol->nodenum, sol->solorigin);
1440 
1441  *feasible = TRUE;
1442 
1443  /* check whether the solution respects the global bounds of the variables */
1444  if( checkbounds )
1445  {
1446  int v;
1447 
1448  for( v = 0; v < prob->nvars && (*feasible || printreason); ++v )
1449  {
1450  SCIP_VAR* var;
1451  SCIP_Real solval;
1452 
1453  var = prob->vars[v];
1454  solval = SCIPsolGetVal(sol, set, stat, var);
1455 
1456  if( solval != SCIP_UNKNOWN ) /*lint !e777*/
1457  {
1458  SCIP_Real lb;
1459  SCIP_Real ub;
1460 
1461  lb = SCIPvarGetLbGlobal(var);
1462  ub = SCIPvarGetUbGlobal(var);
1463  *feasible = *feasible && SCIPsetIsFeasGE(set, solval, lb) && SCIPsetIsFeasLE(set, solval, ub);
1464 
1465  if( printreason && (SCIPsetIsFeasLT(set, solval, lb) || SCIPsetIsFeasGT(set, solval, ub)) )
1466  {
1467  SCIPmessagePrintInfo(messagehdlr, "solution value %g violates bounds of <%s>[%g,%g] by %g\n", solval, SCIPvarGetName(var),
1468  SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), MAX(lb - solval, 0.0) + MAX(solval - ub, 0.0));
1469  }
1470  }
1471 
1472 #ifdef SCIP_DEBUG
1473  if( !(*feasible) && !printreason )
1474  {
1475  SCIPdebugPrintf(" -> solution value %g violates bounds of <%s>[%g,%g]\n", solval, SCIPvarGetName(var),
1477  }
1478 #endif
1479  }
1480  }
1481 
1482  /* check whether there are infinite variable values that lead to an objective value of +infinity */
1483  if( *feasible && sol->hasinfval )
1484  {
1485  int v;
1486 
1487  for( v = 0; v < prob->nvars && (*feasible || printreason); ++v )
1488  {
1489  SCIP_VAR* var;
1490  SCIP_Real solval;
1491 
1492  var = prob->vars[v];
1493  solval = SCIPsolGetVal(sol, set, stat, var);
1494  assert(solval != SCIP_INVALID); /*lint !e777*/
1495 
1496  if( solval != SCIP_UNKNOWN ) /*lint !e777*/
1497  {
1498  *feasible = *feasible && (!SCIPsetIsInfinity(set, solval) || SCIPsetIsLE(set, SCIPvarGetObj(var), 0.0) );
1499  *feasible = *feasible && (!SCIPsetIsInfinity(set, -solval) || SCIPsetIsGE(set, SCIPvarGetObj(var), 0.0) );
1500 
1501  if( printreason && ((SCIPsetIsInfinity(set, solval) && SCIPsetIsGT(set, SCIPvarGetObj(var), 0.0)) ||
1502  (SCIPsetIsInfinity(set, -solval) && SCIPsetIsLT(set, SCIPvarGetObj(var), 0.0))) )
1503  {
1504  SCIPmessagePrintInfo(messagehdlr, "infinite solution value %g for variable <%s> with obj %g implies objective value +infinity\n",
1505  solval, SCIPvarGetName(var), SCIPvarGetObj(var));
1506  }
1507  }
1508 
1509 #ifdef SCIP_DEBUG
1510  if( !(*feasible) && !printreason )
1511  {
1512  SCIPdebugPrintf("infinite solution value %g for variable <%s> with obj %g implies objective value +infinity\n",
1513  solval, SCIPvarGetName(var), SCIPvarGetObj(var));
1514  }
1515 #endif
1516  }
1517  }
1518 
1519  /* check whether the solution fulfills all constraints */
1520  for( h = 0; h < set->nconshdlrs && (*feasible || printreason); ++h )
1521  {
1522  SCIP_CALL( SCIPconshdlrCheck(set->conshdlrs[h], blkmem, set, stat, sol,
1523  checkintegrality, checklprows, printreason, &result) );
1524  *feasible = *feasible && (result == SCIP_FEASIBLE);
1525 
1526 #ifdef SCIP_DEBUG
1527  if( !(*feasible) )
1528  {
1529  SCIPdebugPrintf(" -> infeasibility detected in constraint handler <%s>\n",
1530  SCIPconshdlrGetName(set->conshdlrs[h]));
1531  }
1532 #endif
1533  }
1534 
1535  return SCIP_OKAY;
1536 }
1537 
1538 /** try to round given solution */
1540  SCIP_SOL* sol, /**< primal solution */
1541  SCIP_SET* set, /**< global SCIP settings */
1542  SCIP_STAT* stat, /**< problem statistics data */
1543  SCIP_PROB* prob, /**< transformed problem data */
1544  SCIP_TREE* tree, /**< branch and bound tree */
1545  SCIP_Bool* success /**< pointer to store whether rounding was successful */
1546  )
1547 {
1548  int nvars;
1549  int v;
1550 
1551  assert(sol != NULL);
1552  assert(!SCIPsolIsOriginal(sol));
1553  assert(prob != NULL);
1554  assert(prob->transformed);
1555  assert(success != NULL);
1556 
1557  /* round all roundable fractional variables in the corresponding direction as long as no unroundable var was found */
1558  nvars = prob->nbinvars + prob->nintvars;
1559  for( v = 0; v < nvars; ++v )
1560  {
1561  SCIP_VAR* var;
1562  SCIP_Real solval;
1563  SCIP_Bool mayrounddown;
1564  SCIP_Bool mayroundup;
1565 
1566  var = prob->vars[v];
1568  solval = solGetArrayVal(sol, var);
1569 
1570  /* solutions with unknown entries cannot be rounded */
1571  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1572  break;
1573 
1574  /* if solution value is already integral, there is nothing to do */
1575  if( SCIPsetIsIntegral(set, solval) )
1576  continue;
1577 
1578  /* if solution value is already integral with feastol, round to nearest integral value */
1579  if( SCIPsetIsFeasIntegral(set, solval) )
1580  {
1581  SCIP_CALL( SCIPsolSetVal(sol, set, stat, tree, var, SCIPsetRound(set, solval)) );
1582  continue;
1583  }
1584 
1585  /* get rounding possibilities */
1586  mayrounddown = SCIPvarMayRoundDown(var);
1587  mayroundup = SCIPvarMayRoundUp(var);
1588 
1589  /* choose rounding direction */
1590  if( mayrounddown && mayroundup )
1591  {
1592  /* we can round in both directions: round in objective function direction */
1593  if( SCIPvarGetObj(var) >= 0.0 )
1594  solval = SCIPsetFeasFloor(set, solval);
1595  else
1596  solval = SCIPsetFeasCeil(set, solval);
1597  }
1598  else if( mayrounddown )
1599  solval = SCIPsetFeasFloor(set, solval);
1600  else if( mayroundup )
1601  solval = SCIPsetFeasCeil(set, solval);
1602  else
1603  break;
1604 
1605  /* store new solution value */
1606  SCIP_CALL( SCIPsolSetVal(sol, set, stat, tree, var, solval) );
1607  }
1608 
1609  /* check, if rounding was successful */
1610  *success = (v == nvars);
1611 
1612  return SCIP_OKAY;
1613 }
1614 
1615 /** updates the solution value sums in variables by adding the value in the given solution */
1617  SCIP_SOL* sol, /**< primal CIP solution */
1618  SCIP_SET* set, /**< global SCIP settings */
1619  SCIP_STAT* stat, /**< problem statistics data */
1620  SCIP_PROB* prob, /**< transformed problem data */
1621  SCIP_Real weight /**< weight of solution in weighted average */
1622  )
1623 {
1624  SCIP_Real solval;
1625  int v;
1626 
1627  assert(sol != NULL);
1628  assert(!SCIPsolIsOriginal(sol));
1629  assert(0.0 <= weight && weight <= 1.0);
1630 
1631  for( v = 0; v < prob->nvars; ++v )
1632  {
1633  assert(prob->vars[v] != NULL);
1634  solval = SCIPsolGetVal(sol, set, stat, prob->vars[v]);
1635  if( solval != SCIP_UNKNOWN ) /*lint !e777*/
1636  {
1637  prob->vars[v]->primsolavg *= (1.0-weight);
1638  prob->vars[v]->primsolavg += weight*solval;
1639  }
1640  }
1641 }
1642 
1643 /** retransforms solution to original problem space */
1645  SCIP_SOL* sol, /**< primal CIP solution */
1646  SCIP_SET* set, /**< global SCIP settings */
1647  SCIP_STAT* stat, /**< problem statistics data */
1648  SCIP_PROB* origprob, /**< original problem */
1649  SCIP_PROB* transprob, /**< transformed problem */
1650  SCIP_Bool* hasinfval /**< pointer to store whether the solution has infinite values */
1651  )
1652 {
1653  SCIP_VAR** transvars;
1654  SCIP_VAR** vars;
1655  SCIP_VAR** activevars;
1656  SCIP_Real* solvals;
1657  SCIP_Real* activevals;
1658  SCIP_Real* transsolvals;
1659  SCIP_Real constant;
1660  int requiredsize;
1661  int ntransvars;
1662  int nactivevars;
1663  int nvars;
1664  int v;
1665  int i;
1666 
1667  assert(sol != NULL);
1668  assert(sol->solorigin == SCIP_SOLORIGIN_ZERO);
1669  assert(origprob != NULL);
1670  assert(transprob != NULL);
1671  assert(hasinfval != NULL);
1672  assert(!origprob->transformed);
1673  assert(transprob->transformed);
1674 
1675  *hasinfval = FALSE;
1676 
1677  /* This method was a performance bottleneck when retransforming a solution during presolving, before flattening the
1678  * aggregation graph. In that case, calling SCIPsolGetVal() on the original variable consumed too much
1679  * time. Therefore, we now first compute the active representation of each original variable using
1680  * SCIPvarGetActiveRepresentatives(), which is much faster, and sum up the solution values of the active variables by
1681  * hand for each original variable.
1682  */
1683  vars = origprob->vars;
1684  nvars = origprob->nvars;
1685  transvars = transprob->vars;
1686  ntransvars = transprob->nvars;
1687 
1688  /* allocate temporary memory for getting the active representation of the original variables, buffering the solution
1689  * values of all active variables and storing the original solution values
1690  */
1691  SCIP_CALL( SCIPsetAllocBufferArray(set, &transsolvals, ntransvars + 1) );
1692  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, ntransvars + 1) );
1693  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevals, ntransvars + 1) );
1694  SCIP_CALL( SCIPsetAllocBufferArray(set, &solvals, nvars) );
1695  assert(transsolvals != NULL); /* for flexelint */
1696  assert(solvals != NULL); /* for flexelint */
1697 
1698  /* get the solution values of all active variables */
1699  for( v = 0; v < ntransvars; ++v )
1700  {
1701  transsolvals[v] = SCIPsolGetVal(sol, set, stat, transvars[v]);
1702  }
1703 
1704  /* get the solution in original problem variables */
1705  for( v = 0; v < nvars; ++v )
1706  {
1707  activevars[0] = vars[v];
1708  activevals[0] = 1.0;
1709  nactivevars = 1;
1710  constant = 0.0;
1711 
1712  /* get active representation of the original variable */
1713  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, activevars, activevals, &nactivevars, ntransvars + 1, &constant,
1714  &requiredsize, TRUE) );
1715  assert(requiredsize <= ntransvars);
1716 
1717  /* compute solution value of the original variable */
1718  solvals[v] = constant;
1719  for( i = 0; i < nactivevars; ++i )
1720  {
1721  assert(0 <= SCIPvarGetProbindex(activevars[i]) && SCIPvarGetProbindex(activevars[i]) < ntransvars);
1722  assert(!SCIPsetIsInfinity(set, -solvals[v]) || !SCIPsetIsInfinity(set, activevals[i] * transsolvals[SCIPvarGetProbindex(activevars[i])]));
1723  assert(!SCIPsetIsInfinity(set, solvals[v]) || !SCIPsetIsInfinity(set, -activevals[i] * transsolvals[SCIPvarGetProbindex(activevars[i])]));
1724  solvals[v] += activevals[i] * transsolvals[SCIPvarGetProbindex(activevars[i])];
1725  }
1726 
1727  if( SCIPsetIsInfinity(set, solvals[v]) )
1728  {
1729  solvals[v] = SCIPsetInfinity(set);
1730  *hasinfval = TRUE;
1731  }
1732  else if( SCIPsetIsInfinity(set, -solvals[v]) )
1733  {
1734  solvals[v] = -SCIPsetInfinity(set);
1735  *hasinfval = TRUE;
1736  }
1737  }
1738 
1739  /* clear the solution and convert it into original space */
1740  SCIP_CALL( solClearArrays(sol) );
1742  sol->obj = 0.0;
1743 
1744  /* reinsert the values of the original variables */
1745  for( v = 0; v < nvars; ++v )
1746  {
1747  if( !SCIPsetIsZero(set, solvals[v]) )
1748  {
1749  SCIP_CALL( solSetArrayVal(sol, set, vars[v], solvals[v]) );
1750  if( solvals[v] != SCIP_UNKNOWN ) /*lint !e777*/
1751  sol->obj += SCIPvarGetObj(vars[v]) * solvals[v];
1752  }
1753  }
1754 
1755  /**@todo remember the variables without original counterpart (priced variables) in the solution */
1756 
1757  /* free temporary memory */
1758  SCIPsetFreeBufferArray(set, &solvals);
1759  SCIPsetFreeBufferArray(set, &activevals);
1760  SCIPsetFreeBufferArray(set, &activevars);
1761  SCIPsetFreeBufferArray(set, &transsolvals);
1762 
1763  return SCIP_OKAY;
1764 }
1765 
1766 /** recomputes the objective value of an original solution, e.g., when transferring solutions
1767  * from the solution pool (objective coefficients might have changed in the meantime)
1768  */
1770  SCIP_SOL* sol, /**< primal CIP solution */
1771  SCIP_SET* set, /**< global SCIP settings */
1772  SCIP_STAT* stat, /**< problem statistics data */
1773  SCIP_PROB* origprob /**< original problem */
1774  )
1775 {
1776  SCIP_VAR** vars;
1777  SCIP_Real solval;
1778  int nvars;
1779  int v;
1780 
1781  assert(sol != NULL);
1782  assert(SCIPsolIsOriginal(sol));
1783  assert(origprob != NULL);
1784 
1785  vars = origprob->vars;
1786  nvars = origprob->nvars;
1787 
1788  /* recompute the objective value */
1789  sol->obj = SCIPprobGetObjoffset(origprob);
1790  for( v = 0; v < nvars; ++v )
1791  {
1792  solval = SCIPsolGetVal(sol, set, stat, vars[v]);
1793  if( !SCIPsetIsZero(set, solval) && solval != SCIP_UNKNOWN ) /*lint !e777*/
1794  {
1795  sol->obj += SCIPvarGetObj(vars[v]) * solval;
1796  }
1797  }
1798 
1799  if( SCIPsetIsInfinity(set, -sol->obj) )
1800  sol->obj = -SCIPsetInfinity(set);
1801 }
1802 
1803 /** returns whether the given solutions are equal */
1805  SCIP_SOL* sol1, /**< first primal CIP solution */
1806  SCIP_SOL* sol2, /**< second primal CIP solution */
1807  SCIP_SET* set, /**< global SCIP settings */
1808  SCIP_STAT* stat, /**< problem statistics data */
1809  SCIP_PROB* origprob, /**< original problem */
1810  SCIP_PROB* transprob /**< transformed problem after presolve, or NULL if both solution are
1811  * defined in the original problem space */
1812  )
1813 {
1814  SCIP_PROB* prob;
1815  SCIP_Real obj1;
1816  SCIP_Real obj2;
1817  int v;
1818 
1819  assert(sol1 != NULL);
1820  assert(sol2 != NULL);
1821  assert((SCIPsolIsOriginal(sol1) && SCIPsolIsOriginal(sol2)) || transprob != NULL);
1822 
1823  /* if both solutions are original or both are transformed, take the objective values stored in the solutions */
1824  if( SCIPsolIsOriginal(sol1) == SCIPsolIsOriginal(sol2) )
1825  {
1826  obj1 = sol1->obj;
1827  obj2 = sol2->obj;
1828  }
1829  /* one solution is original and the other not, so we have to get for both the objective in the transformed problem */
1830  else
1831  {
1832  obj1 = SCIPsolGetObj(sol1, set, transprob, origprob);
1833  obj2 = SCIPsolGetObj(sol2, set, transprob, origprob);
1834  }
1835 
1836  /* solutions with different objective values cannot be the same */
1837  if( !SCIPsetIsEQ(set, obj1, obj2) )
1838  return FALSE;
1839 
1840  /* if one of the solutions is defined in the original space, the comparison has to be performed in the original
1841  * space
1842  */
1843  prob = transprob;
1844  if( SCIPsolIsOriginal(sol1) || SCIPsolIsOriginal(sol2) )
1845  prob = origprob;
1846  assert(prob != NULL);
1847 
1848  /* compare each variable value */
1849  for( v = 0; v < prob->nvars; ++v )
1850  {
1851  SCIP_Real val1;
1852  SCIP_Real val2;
1853 
1854  val1 = SCIPsolGetVal(sol1, set, stat, prob->vars[v]);
1855  val2 = SCIPsolGetVal(sol2, set, stat, prob->vars[v]);
1856  if( !SCIPsetIsEQ(set, val1, val2) )
1857  return FALSE;
1858  }
1859 
1860  return TRUE;
1861 }
1862 
1863 /** outputs non-zero elements of solution to file stream */
1865  SCIP_SOL* sol, /**< primal CIP solution */
1866  SCIP_SET* set, /**< global SCIP settings */
1867  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1868  SCIP_STAT* stat, /**< problem statistics data */
1869  SCIP_PROB* prob, /**< problem data (original or transformed) */
1870  SCIP_PROB* transprob, /**< transformed problem data or NULL (to display priced variables) */
1871  FILE* file, /**< output file (or NULL for standard output) */
1872  SCIP_Bool printzeros /**< should variables set to zero be printed? */
1873  )
1874 {
1875  SCIP_Real solval;
1876  int v;
1877 
1878  assert(sol != NULL);
1879  assert(prob != NULL);
1880  assert(SCIPsolIsOriginal(sol) || prob->transformed || transprob != NULL);
1881 
1882  /* display variables of problem data */
1883  for( v = 0; v < prob->nfixedvars; ++v )
1884  {
1885  assert(prob->fixedvars[v] != NULL);
1886  solval = SCIPsolGetVal(sol, set, stat, prob->fixedvars[v]);
1887  if( printzeros || !SCIPsetIsZero(set, solval) )
1888  {
1889  SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(prob->fixedvars[v]));
1890  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1891  SCIPmessageFPrintInfo(messagehdlr, file, " unknown");
1892  else if( SCIPsetIsInfinity(set, solval) )
1893  SCIPmessageFPrintInfo(messagehdlr, file, " +infinity");
1894  else if( SCIPsetIsInfinity(set, -solval) )
1895  SCIPmessageFPrintInfo(messagehdlr, file, " -infinity");
1896  else
1897  SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval);
1898  SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetObj(prob->fixedvars[v]));
1899  }
1900  }
1901 
1902  for( v = 0; v < prob->nvars; ++v )
1903  {
1904  assert(prob->vars[v] != NULL);
1905  solval = SCIPsolGetVal(sol, set, stat, prob->vars[v]);
1906  if( printzeros || !SCIPsetIsZero(set, solval) )
1907  {
1908  SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(prob->vars[v]));
1909  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1910  SCIPmessageFPrintInfo(messagehdlr, file, " unknown");
1911  else if( SCIPsetIsInfinity(set, solval) )
1912  SCIPmessageFPrintInfo(messagehdlr, file, " +infinity");
1913  else if( SCIPsetIsInfinity(set, -solval) )
1914  SCIPmessageFPrintInfo(messagehdlr, file, " -infinity");
1915  else
1916  SCIPmessageFPrintInfo(messagehdlr, file, " %20.15g", solval);
1917  SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetObj(prob->vars[v]));
1918  }
1919  }
1920 
1921  /* display additional priced variables (if given problem data is original problem) */
1922  if( !prob->transformed && !SCIPsolIsOriginal(sol) )
1923  {
1924  assert(transprob != NULL);
1925  for( v = 0; v < transprob->nfixedvars; ++v )
1926  {
1927  assert(transprob->fixedvars[v] != NULL);
1928  if( SCIPvarIsTransformedOrigvar(transprob->fixedvars[v]) )
1929  continue;
1930 
1931  solval = SCIPsolGetVal(sol, set, stat, transprob->fixedvars[v]);
1932  if( printzeros || !SCIPsetIsZero(set, solval) )
1933  {
1934  SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(transprob->fixedvars[v]));
1935  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1936  SCIPmessageFPrintInfo(messagehdlr, file, " unknown");
1937  else if( SCIPsetIsInfinity(set, solval) )
1938  SCIPmessageFPrintInfo(messagehdlr, file, " +infinity");
1939  else if( SCIPsetIsInfinity(set, -solval) )
1940  SCIPmessageFPrintInfo(messagehdlr, file, " -infinity");
1941  else
1942  SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval);
1943  SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetObj(transprob->fixedvars[v]));
1944  }
1945  }
1946  for( v = 0; v < transprob->nvars; ++v )
1947  {
1948  assert(transprob->vars[v] != NULL);
1949  if( SCIPvarIsTransformedOrigvar(transprob->vars[v]) )
1950  continue;
1951 
1952  solval = SCIPsolGetVal(sol, set, stat, transprob->vars[v]);
1953  if( printzeros || !SCIPsetIsZero(set, solval) )
1954  {
1955  SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(transprob->vars[v]));
1956  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1957  SCIPmessageFPrintInfo(messagehdlr, file, " unknown");
1958  else if( SCIPsetIsInfinity(set, solval) )
1959  SCIPmessageFPrintInfo(messagehdlr, file, " +infinity");
1960  else if( SCIPsetIsInfinity(set, -solval) )
1961  SCIPmessageFPrintInfo(messagehdlr, file, " -infinity");
1962  else
1963  SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval);
1964  SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetObj(transprob->vars[v]));
1965  }
1966  }
1967  }
1968 
1969  return SCIP_OKAY;
1970 }
1971 
1972 /** outputs non-zero elements of solution representing a ray to file stream */
1974  SCIP_SOL* sol, /**< primal CIP solution */
1975  SCIP_SET* set, /**< global SCIP settings */
1976  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1977  SCIP_STAT* stat, /**< problem statistics data */
1978  SCIP_PROB* prob, /**< problem data (original or transformed) */
1979  SCIP_PROB* transprob, /**< transformed problem data or NULL (to display priced variables) */
1980  FILE* file, /**< output file (or NULL for standard output) */
1981  SCIP_Bool printzeros /**< should variables set to zero be printed? */
1982  )
1983 {
1984  SCIP_Real solval;
1985  int v;
1986 
1987  assert(sol != NULL);
1988  assert(prob != NULL);
1989  assert(SCIPsolIsOriginal(sol) || prob->transformed || transprob != NULL);
1990 
1991  /* display variables of problem data */
1992  for( v = 0; v < prob->nfixedvars; ++v )
1993  {
1994  assert(prob->fixedvars[v] != NULL);
1995  solval = SCIPsolGetRayVal(sol, set, stat, prob->fixedvars[v]);
1996  if( printzeros || !SCIPsetIsZero(set, solval) )
1997  {
1998  SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(prob->fixedvars[v]));
1999  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
2000  SCIPmessageFPrintInfo(messagehdlr, file, " unknown");
2001  else if( SCIPsetIsInfinity(set, solval) )
2002  SCIPmessageFPrintInfo(messagehdlr, file, " +infinity");
2003  else if( SCIPsetIsInfinity(set, -solval) )
2004  SCIPmessageFPrintInfo(messagehdlr, file, " -infinity");
2005  else
2006  SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval);
2007  SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetObj(prob->fixedvars[v]));
2008  }
2009  }
2010  for( v = 0; v < prob->nvars; ++v )
2011  {
2012  assert(prob->vars[v] != NULL);
2013  solval = SCIPsolGetRayVal(sol, set, stat, prob->vars[v]);
2014  if( printzeros || !SCIPsetIsZero(set, solval) )
2015  {
2016  SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(prob->vars[v]));
2017  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
2018  SCIPmessageFPrintInfo(messagehdlr, file, " unknown");
2019  else if( SCIPsetIsInfinity(set, solval) )
2020  SCIPmessageFPrintInfo(messagehdlr, file, " +infinity");
2021  else if( SCIPsetIsInfinity(set, -solval) )
2022  SCIPmessageFPrintInfo(messagehdlr, file, " -infinity");
2023  else
2024  SCIPmessageFPrintInfo(messagehdlr, file, " %20.15g", solval);
2025  SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetObj(prob->vars[v]));
2026  }
2027  }
2028 
2029  /* display additional priced variables (if given problem data is original problem) */
2030  if( !prob->transformed && !SCIPsolIsOriginal(sol) )
2031  {
2032  assert(transprob != NULL);
2033  for( v = 0; v < transprob->nfixedvars; ++v )
2034  {
2035  assert(transprob->fixedvars[v] != NULL);
2036  if( SCIPvarIsTransformedOrigvar(transprob->fixedvars[v]) )
2037  continue;
2038 
2039  solval = SCIPsolGetRayVal(sol, set, stat, transprob->fixedvars[v]);
2040  if( printzeros || !SCIPsetIsZero(set, solval) )
2041  {
2042  SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(transprob->fixedvars[v]));
2043  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
2044  SCIPmessageFPrintInfo(messagehdlr, file, " unknown");
2045  else if( SCIPsetIsInfinity(set, solval) )
2046  SCIPmessageFPrintInfo(messagehdlr, file, " +infinity");
2047  else if( SCIPsetIsInfinity(set, -solval) )
2048  SCIPmessageFPrintInfo(messagehdlr, file, " -infinity");
2049  else
2050  SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval);
2051  SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetObj(transprob->fixedvars[v]));
2052  }
2053  }
2054  for( v = 0; v < transprob->nvars; ++v )
2055  {
2056  assert(transprob->vars[v] != NULL);
2057  if( SCIPvarIsTransformedOrigvar(transprob->vars[v]) )
2058  continue;
2059 
2060  solval = SCIPsolGetRayVal(sol, set, stat, transprob->vars[v]);
2061  if( printzeros || !SCIPsetIsZero(set, solval) )
2062  {
2063  SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(transprob->vars[v]));
2064  if( solval == SCIP_UNKNOWN ) /*lint !e777*/
2065  SCIPmessageFPrintInfo(messagehdlr, file, " unknown");
2066  else if( SCIPsetIsInfinity(set, solval) )
2067  SCIPmessageFPrintInfo(messagehdlr, file, " +infinity");
2068  else if( SCIPsetIsInfinity(set, -solval) )
2069  SCIPmessageFPrintInfo(messagehdlr, file, " -infinity");
2070  else
2071  SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval);
2072  SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetObj(transprob->vars[v]));
2073  }
2074  }
2075  }
2076 
2077  return SCIP_OKAY;
2078 }
2079 
2080 
2081 
2082 
2083 /*
2084  * simple functions implemented as defines
2085  */
2086 
2087 /* In debug mode, the following methods are implemented as function calls to ensure
2088  * type validity.
2089  * In optimized mode, the methods are implemented as defines to improve performance.
2090  * However, we want to have them in the library anyways, so we have to undef the defines.
2091  */
2092 
2093 #undef SCIPsolGetOrigin
2094 #undef SCIPsolIsOriginal
2095 #undef SCIPsolGetOrigObj
2096 #undef SCIPsolGetTime
2097 #undef SCIPsolGetNodenum
2098 #undef SCIPsolGetRunnum
2099 #undef SCIPsolGetDepth
2100 #undef SCIPsolGetHeur
2101 #undef SCIPsolOrigAddObjval
2102 #undef SCIPsolGetPrimalIndex
2103 #undef SCIPsolSetPrimalIndex
2104 #undef SCIPsolGetIndex
2105 #undef SCIPsolSetHeur
2106 
2107 /** gets origin of solution */
2109  SCIP_SOL* sol /**< primal CIP solution */
2110  )
2111 {
2112  assert(sol != NULL);
2113 
2114  return sol->solorigin;
2115 }
2116 
2117 /** returns whether the given solution is defined on original variables */
2119  SCIP_SOL* sol /**< primal CIP solution */
2120  )
2121 {
2122  assert(sol != NULL);
2123 
2124  return (sol->solorigin == SCIP_SOLORIGIN_ORIGINAL);
2125 }
2126 
2127 /** gets objective value of primal CIP solution which lives in the original problem space */
2129  SCIP_SOL* sol /**< primal CIP solution */
2130  )
2131 {
2132  assert(sol != NULL);
2133  assert(SCIPsolIsOriginal(sol));
2134 
2135  return sol->obj;
2136 }
2137 
2138 /** adds value to the objective value of a given original primal CIP solution */
2140  SCIP_SOL* sol, /**< primal CIP solution */
2141  SCIP_Real addval /**< offset value to add */
2142  )
2143 {
2144  assert(sol != NULL);
2145  assert(sol->solorigin == SCIP_SOLORIGIN_ORIGINAL);
2146 
2147  sol->obj += addval;
2148 }
2149 
2150 /** gets clock time, when this solution was found */
2152  SCIP_SOL* sol /**< primal CIP solution */
2153  )
2154 {
2155  assert(sol != NULL);
2156 
2157  return sol->time;
2158 }
2159 
2160 /** gets branch and bound run number, where this solution was found */
2162  SCIP_SOL* sol /**< primal CIP solution */
2163  )
2164 {
2165  assert(sol != NULL);
2166 
2167  return sol->runnum;
2168 }
2169 
2170 /** gets node number, where this solution was found */
2172  SCIP_SOL* sol /**< primal CIP solution */
2173  )
2174 {
2175  assert(sol != NULL);
2176 
2177  return sol->nodenum;
2178 }
2179 
2180 /** gets node's depth, where this solution was found */
2182  SCIP_SOL* sol /**< primal CIP solution */
2183  )
2184 {
2185  assert(sol != NULL);
2186 
2187  return sol->depth;
2188 }
2189 
2190 /** gets heuristic, that found this solution (or NULL if it's from the tree) */
2192  SCIP_SOL* sol /**< primal CIP solution */
2193  )
2194 {
2195  assert(sol != NULL);
2196 
2197  return sol->heur;
2198 }
2199 
2200 /** gets current position of solution in array of existing solutions of primal data */
2202  SCIP_SOL* sol /**< primal CIP solution */
2203  )
2204 {
2205  assert(sol != NULL);
2206 
2207  return sol->primalindex;
2208 }
2209 
2210 /** sets current position of solution in array of existing solutions of primal data */
2212  SCIP_SOL* sol, /**< primal CIP solution */
2213  int primalindex /**< new primal index of solution */
2214  )
2215 {
2216  assert(sol != NULL);
2217 
2218  sol->primalindex = primalindex;
2219 }
2220 
2221 /** returns unique index of given solution */
2223  SCIP_SOL* sol /**< primal CIP solution */
2224  )
2225 {
2226  assert(sol != NULL);
2227 
2228  return sol->index;
2229 }
2230 
2231 /** informs the solution that it now belongs to the given primal heuristic */
2233  SCIP_SOL* sol, /**< primal CIP solution */
2234  SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */
2235  )
2236 {
2237  assert(sol != NULL);
2238 
2239  sol->heur = heur;
2240 }
2241 
2242