1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*  Copyright (c) 2002-2023 Zuse Institute Berlin (ZIB)                      */
7    	/*                                                                           */
8    	/*  Licensed under the Apache License, Version 2.0 (the "License");          */
9    	/*  you may not use this file except in compliance with the License.         */
10   	/*  You may obtain a copy of the License at                                  */
11   	/*                                                                           */
12   	/*      http://www.apache.org/licenses/LICENSE-2.0                           */
13   	/*                                                                           */
14   	/*  Unless required by applicable law or agreed to in writing, software      */
15   	/*  distributed under the License is distributed on an "AS IS" BASIS,        */
16   	/*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17   	/*  See the License for the specific language governing permissions and      */
18   	/*  limitations under the License.                                           */
19   	/*                                                                           */
20   	/*  You should have received a copy of the Apache-2.0 license                */
21   	/*  along with SCIP; see the file LICENSE. If not visit scipopt.org.         */
22   	/*                                                                           */
23   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24   	
25   	/**@file   sol.c
26   	 * @ingroup OTHER_CFILES
27   	 * @brief  methods for storing primal CIP solutions
28   	 * @author Tobias Achterberg
29   	 */
30   	
31   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32   	
33   	#include "scip/clock.h"
34   	#include "scip/cons.h"
35   	#include "scip/lp.h"
36   	#include "scip/misc.h"
37   	#include "scip/nlp.h"
38   	#include "scip/primal.h"
39   	#include "scip/prob.h"
40   	#include "scip/pub_lp.h"
41   	#include "scip/pub_message.h"
42   	#include "scip/pub_sol.h"
43   	#include "scip/pub_var.h"
44   	#include "scip/relax.h"
45   	#include "scip/set.h"
46   	#include "scip/sol.h"
47   	#include "scip/stat.h"
48   	#include "scip/struct_lp.h"
49   	#include "scip/struct_prob.h"
50   	#include "scip/struct_set.h"
51   	#include "scip/struct_sol.h"
52   	#include "scip/struct_stat.h"
53   	#include "scip/struct_var.h"
54   	#include "scip/tree.h"
55   	#include "scip/var.h"
56   	
57   	
58   	
59   	/** clears solution arrays of primal CIP solution */
60   	static
61   	SCIP_RETCODE solClearArrays(
62   	   SCIP_SOL*             sol                 /**< primal CIP solution */
63   	   )
64   	{
65   	   assert(sol != NULL);
66   	
67   	   SCIP_CALL( SCIPboolarrayClear(sol->valid) );
68   	   sol->hasinfval = FALSE;
69   	
70   	   return SCIP_OKAY;
71   	}
72   	
73   	/** sets value of variable in the solution's array */
74   	static
75   	SCIP_RETCODE solSetArrayVal(
76   	   SCIP_SOL*             sol,                /**< primal CIP solution */
77   	   SCIP_SET*             set,                /**< global SCIP settings */
78   	   SCIP_VAR*             var,                /**< problem variable */
79   	   SCIP_Real             val                 /**< value to set variable to */
80   	   )
81   	{
82   	   int idx;
83   	
84   	   assert(sol != NULL);
85   	
86   	   idx = SCIPvarGetIndex(var);
87   	
88   	   /* from now on, variable must not be deleted */
89   	   SCIPvarMarkNotDeletable(var);
90   	
91   	   /* mark the variable valid */
92   	   SCIP_CALL( SCIPboolarraySetVal(sol->valid, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, TRUE) );
93   	
94   	   /* set the value in the solution array */
95   	   SCIP_CALL( SCIPrealarraySetVal(sol->vals, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, val) );
96   	
97   	   /* store whether the solution has infinite values assigned to variables */
98   	   if( val != SCIP_UNKNOWN ) /*lint !e777*/
99   	      sol->hasinfval = (sol->hasinfval || SCIPsetIsInfinity(set, val) || SCIPsetIsInfinity(set, -val));
100  	
101  	   return SCIP_OKAY;
102  	}
103  	
104  	/** increases value of variable in the solution's array */
105  	static
106  	SCIP_RETCODE solIncArrayVal(
107  	   SCIP_SOL*             sol,                /**< primal CIP solution */
108  	   SCIP_SET*             set,                /**< global SCIP settings */
109  	   SCIP_VAR*             var,                /**< problem variable */
110  	   SCIP_Real             incval              /**< increase of variable's solution value */
111  	   )
112  	{
113  	   int idx;
114  	
115  	   assert(sol != NULL);
116  	
117  	   idx = SCIPvarGetIndex(var);
118  	
119  	   /* from now on, variable must not be deleted */
120  	   SCIPvarMarkNotDeletable(var);
121  	
122  	   /* 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) */
123  	   if( !SCIPboolarrayGetVal(sol->valid, idx) )
124  	   {
125  	      /* mark the variable valid */
126  	      SCIP_CALL( SCIPboolarraySetVal(sol->valid, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, TRUE) );
127  	
128  	      /* set the value in the solution array */
129  	      SCIP_CALL( SCIPrealarraySetVal(sol->vals, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, incval) );
130  	   }
131  	   else
132  	   {
133  	      /* increase the value in the solution array */
134  	      SCIP_CALL( SCIPrealarrayIncVal(sol->vals, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, incval) );
135  	   }
136  	
137  	   /* store whether the solution has infinite values assigned to variables */
138  	   incval = SCIPrealarrayGetVal(sol->vals, idx);
139  	   if( incval != SCIP_UNKNOWN ) /*lint !e777*/
140  	      sol->hasinfval = (sol->hasinfval || SCIPsetIsInfinity(set, incval) || SCIPsetIsInfinity(set, -incval));
141  	
142  	   return SCIP_OKAY;
143  	}
144  	
145  	/** returns the value of the variable in the given solution */
146  	static
147  	SCIP_Real solGetArrayVal(
148  	   SCIP_SOL*             sol,                /**< primal CIP solution */
149  	   SCIP_VAR*             var                 /**< problem variable */
150  	   )
151  	{
152  	   int idx;
153  	
154  	   assert(sol != NULL);
155  	
156  	   idx = SCIPvarGetIndex(var);
157  	
158  	   /* check, if the variable's value is valid */
159  	   if( SCIPboolarrayGetVal(sol->valid, idx) )
160  	   {
161  	      return SCIPrealarrayGetVal(sol->vals, idx);
162  	   }
163  	   else
164  	   {
165  	      /* return the variable's value corresponding to the origin */
166  	      switch( sol->solorigin )
167  	      {
168  	      case SCIP_SOLORIGIN_ORIGINAL:
169  	      case SCIP_SOLORIGIN_ZERO:
170  	         return 0.0;
171  	
172  	      case SCIP_SOLORIGIN_LPSOL:
173  	         return SCIPvarGetLPSol(var);
174  	
175  	      case SCIP_SOLORIGIN_NLPSOL:
176  	         return SCIPvarGetNLPSol(var);
177  	
178  	      case SCIP_SOLORIGIN_RELAXSOL:
179  	         return SCIPvarGetRelaxSolTransVar(var);
180  	
181  	      case SCIP_SOLORIGIN_PSEUDOSOL:
182  	         return SCIPvarGetPseudoSol(var);
183  	
184  	      case SCIP_SOLORIGIN_PARTIAL:
185  	      case SCIP_SOLORIGIN_UNKNOWN:
186  	         return SCIP_UNKNOWN;
187  	
188  	      default:
189  	         SCIPerrorMessage("unknown solution origin <%d>\n", sol->solorigin);
190  	         SCIPABORT();
191  	         return 0.0; /*lint !e527*/
192  	      }
193  	   }
194  	}
195  	
196  	/** stores solution value of variable in solution's own array */
197  	static
198  	SCIP_RETCODE solUnlinkVar(
199  	   SCIP_SOL*             sol,                /**< primal CIP solution */
200  	   SCIP_SET*             set,                /**< global SCIP settings */
201  	   SCIP_VAR*             var                 /**< problem variable */
202  	   )
203  	{
204  	   SCIP_Real solval;
205  	
206  	   assert(sol != NULL);
207  	   assert(var != NULL);
208  	   assert(SCIPvarIsTransformed(var));
209  	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
210  	
211  	   /* if variable is already valid, nothing has to be done */
212  	   if( SCIPboolarrayGetVal(sol->valid, SCIPvarGetIndex(var)) )
213  	      return SCIP_OKAY;
214  	
215  	   SCIPsetDebugMsg(set, "unlinking solution value of variable <%s>\n", SCIPvarGetName(var));
216  	
217  	   /* store the correct solution value into the solution array */
218  	   switch( sol->solorigin )
219  	   {
220  	   case SCIP_SOLORIGIN_ORIGINAL:
221  	      SCIPerrorMessage("cannot unlink solutions of original problem space\n");
222  	      return SCIP_INVALIDDATA;
223  	
224  	   case SCIP_SOLORIGIN_ZERO:
225  	      return SCIP_OKAY;
226  	
227  	   case SCIP_SOLORIGIN_LPSOL:
228  	      solval = SCIPvarGetLPSol(var);
229  	      SCIP_CALL( solSetArrayVal(sol, set, var, solval) );
230  	      return SCIP_OKAY;
231  	
232  	   case SCIP_SOLORIGIN_NLPSOL:
233  	      solval = SCIPvarGetNLPSol(var);
234  	      SCIP_CALL( solSetArrayVal(sol, set, var, solval) );
235  	      return SCIP_OKAY;
236  	
237  	   case SCIP_SOLORIGIN_RELAXSOL:
238  	      solval = SCIPvarGetRelaxSolTransVar(var);
239  	      SCIP_CALL( solSetArrayVal(sol, set, var, solval) );
240  	      return SCIP_OKAY;
241  	
242  	   case SCIP_SOLORIGIN_PSEUDOSOL:
243  	      solval = SCIPvarGetPseudoSol(var);
244  	      SCIP_CALL( solSetArrayVal(sol, set, var, solval) );
245  	      return SCIP_OKAY;
246  	
247  	   case SCIP_SOLORIGIN_PARTIAL:
248  	   case SCIP_SOLORIGIN_UNKNOWN:
249  	      SCIP_CALL( solSetArrayVal(sol, set, var, SCIP_UNKNOWN) );
250  	      return SCIP_OKAY;
251  	
252  	   default:
253  	      SCIPerrorMessage("unknown solution origin <%d>\n", sol->solorigin);
254  	      return SCIP_INVALIDDATA;
255  	   }
256  	}
257  	
258  	/** sets the solution time, nodenum, runnum, and depth stamp to the current values */
259  	static
260  	void solStamp(
261  	   SCIP_SOL*             sol,                /**< primal CIP solution */
262  	   SCIP_STAT*            stat,               /**< problem statistics data */
263  	   SCIP_TREE*            tree,               /**< branch and bound tree, or NULL */
264  	   SCIP_Bool             checktime           /**< should the time be updated? */
265  	   )
266  	{
267  	   assert(sol != NULL);
268  	   assert(stat != NULL);
269  	
270  	   if( checktime )
271  	   {
272  	      sol->time = SCIPclockGetTime(stat->solvingtime);
273  	#ifndef NDEBUG
274  	      sol->lpcount = stat->lpcount;
275  	#endif
276  	   }
277  	   else
278  	      sol->time = SCIPclockGetLastTime(stat->solvingtime);
279  	   sol->nodenum = stat->nnodes;
280  	   sol->runnum = stat->nruns;
281  	   if( tree == NULL )
282  	      sol->depth = -1;
283  	   else
284  	      sol->depth = SCIPtreeGetCurrentDepth(tree);
285  	}
286  	
287  	/** creates primal CIP solution, initialized to zero */
288  	SCIP_RETCODE SCIPsolCreate(
289  	   SCIP_SOL**            sol,                /**< pointer to primal CIP solution */
290  	   BMS_BLKMEM*           blkmem,             /**< block memory */
291  	   SCIP_SET*             set,                /**< global SCIP settings */
292  	   SCIP_STAT*            stat,               /**< problem statistics data */
293  	   SCIP_PRIMAL*          primal,             /**< primal data */
294  	   SCIP_TREE*            tree,               /**< branch and bound tree */
295  	   SCIP_HEUR*            heur                /**< heuristic that found the solution (or NULL if it's from the tree) */
296  	   )
297  	{
298  	   assert(sol != NULL);
299  	   assert(blkmem != NULL);
300  	   assert(stat != NULL);
301  	
302  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, sol) );
303  	   SCIP_CALL( SCIPrealarrayCreate(&(*sol)->vals, blkmem) );
304  	   SCIP_CALL( SCIPboolarrayCreate(&(*sol)->valid, blkmem) );
305  	
306  	   (*sol)->solorigin = SCIP_SOLORIGIN_ZERO;
307  	   (*sol)->obj = 0.0;
308  	   (*sol)->primalindex = -1;
309  	   (*sol)->index = stat->solindex;
310  	   (*sol)->hasinfval = FALSE;
311  	   SCIPsolResetViolations(*sol);
312  	   stat->solindex++;
313  	   solStamp(*sol, stat, tree, TRUE);
314  	   SCIPsolResetViolations(*sol);
315  	
316  	   /* set solution type and creator depending on whether a heuristic or NULL is passed */
317  	   SCIPsolSetHeur(*sol, heur);
318  	
319  	   SCIP_CALL( SCIPprimalSolCreated(primal, set, *sol) );
320  	
321  	   return SCIP_OKAY;
322  	}
323  	
324  	/** creates primal CIP solution in original problem space, initialized to the offset in the original problem */
325  	SCIP_RETCODE SCIPsolCreateOriginal(
326  	   SCIP_SOL**            sol,                /**< pointer to primal CIP solution */
327  	   BMS_BLKMEM*           blkmem,             /**< block memory */
328  	   SCIP_SET*             set,                /**< global SCIP settings */
329  	   SCIP_STAT*            stat,               /**< problem statistics data */
330  	   SCIP_PROB*            origprob,           /**< original problem data */
331  	   SCIP_PRIMAL*          primal,             /**< primal data */
332  	   SCIP_TREE*            tree,               /**< branch and bound tree */
333  	   SCIP_HEUR*            heur                /**< heuristic that found the solution (or NULL if it's from the tree) */
334  	   )
335  	{
336  	   assert(sol != NULL);
337  	   assert(blkmem != NULL);
338  	   assert(stat != NULL);
339  	
340  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, sol) );
341  	   SCIP_CALL( SCIPrealarrayCreate(&(*sol)->vals, blkmem) );
342  	   SCIP_CALL( SCIPboolarrayCreate(&(*sol)->valid, blkmem) );
343  	   (*sol)->solorigin = SCIP_SOLORIGIN_ORIGINAL;
344  	   (*sol)->obj = origprob->objoffset;
345  	   (*sol)->primalindex = -1;
346  	   (*sol)->index = stat->solindex;
347  	   (*sol)->hasinfval = FALSE;
348  	   stat->solindex++;
349  	   solStamp(*sol, stat, tree, TRUE);
350  	
351  	   /* set solution type and creator depending on whether a heuristic or NULL is passed */
352  	   SCIPsolSetHeur(*sol, heur);
353  	
354  	   SCIPsolResetViolations(*sol);
355  	
356  	   SCIP_CALL( SCIPprimalSolCreated(primal, set, *sol) );
357  	
358  	   return SCIP_OKAY;
359  	}
360  	
361  	/** creates a copy of a primal CIP solution */
362  	SCIP_RETCODE SCIPsolCopy(
363  	   SCIP_SOL**            sol,                /**< pointer to store the copy of the primal CIP solution */
364  	   BMS_BLKMEM*           blkmem,             /**< block memory */
365  	   SCIP_SET*             set,                /**< global SCIP settings */
366  	   SCIP_STAT*            stat,               /**< problem statistics data */
367  	   SCIP_PRIMAL*          primal,             /**< primal data */
368  	   SCIP_SOL*             sourcesol           /**< primal CIP solution to copy */
369  	   )
370  	{
371  	   assert(sol != NULL);
372  	   assert(sourcesol != NULL);
373  	
374  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, sol) );
375  	   SCIP_CALL( SCIPrealarrayCopy(&(*sol)->vals, blkmem, sourcesol->vals) );
376  	   SCIP_CALL( SCIPboolarrayCopy(&(*sol)->valid, blkmem, sourcesol->valid) );
377  	
378  	   /* copy solution type and creator information */
379  	   switch( sourcesol->type )
380  	   {
381  	   case SCIP_SOLTYPE_UNKNOWN:
382  	   case SCIP_SOLTYPE_LPRELAX:
383  	   case SCIP_SOLTYPE_STRONGBRANCH:
384  	   case SCIP_SOLTYPE_PSEUDO:
385  	      (*sol)->type = sourcesol->type;
386  	      break;
387  	   case SCIP_SOLTYPE_HEUR:
388  	      SCIPsolSetHeur((*sol), SCIPsolGetHeur(sourcesol));
389  	      break;
390  	   case SCIP_SOLTYPE_RELAX:
391  	      SCIPsolSetRelax((*sol), SCIPsolGetRelax(sourcesol));
392  	      break;
393  	   default:
394  	      SCIPerrorMessage("Unknown source solution type %d!\n", sourcesol->type);
395  	      return SCIP_INVALIDDATA;
396  	   }
397  	   (*sol)->obj = sourcesol->obj;
398  	   (*sol)->primalindex = -1;
399  	   (*sol)->time = sourcesol->time;
400  	#ifndef NDEBUG
401  	   (*sol)->lpcount = sourcesol->lpcount;
402  	#endif
403  	   (*sol)->nodenum = sourcesol->nodenum;
404  	   (*sol)->solorigin = sourcesol->solorigin;
405  	   (*sol)->runnum = sourcesol->runnum;
406  	   (*sol)->depth = sourcesol->depth;
407  	   (*sol)->index = stat->solindex;
408  	   (*sol)->hasinfval = sourcesol->hasinfval;
409  	   stat->solindex++;
410  	   (*sol)->viol.absviolbounds = sourcesol->viol.absviolbounds;
411  	   (*sol)->viol.absviolcons = sourcesol->viol.absviolcons;
412  	   (*sol)->viol.absviolintegrality = sourcesol->viol.absviolintegrality;
413  	   (*sol)->viol.absviollprows = sourcesol->viol.absviollprows;
414  	   (*sol)->viol.relviolbounds = sourcesol->viol.relviolbounds;
415  	   (*sol)->viol.relviolcons = sourcesol->viol.relviolcons;
416  	   (*sol)->viol.relviollprows = sourcesol->viol.relviollprows;
417  	
418  	   SCIP_CALL( SCIPprimalSolCreated(primal, set, *sol) );
419  	
420  	   return SCIP_OKAY;
421  	}
422  	
423  	/** transformes given original solution to the transformed space; a corresponding transformed solution has to be given
424  	 *  which is copied into the existing solution and freed afterwards
425  	 */
426  	SCIP_RETCODE SCIPsolTransform(
427  	   SCIP_SOL*             sol,                /**< primal CIP solution to change, living in original space */
428  	   SCIP_SOL**            transsol,           /**< pointer to corresponding transformed primal CIP solution */
429  	   BMS_BLKMEM*           blkmem,             /**< block memory */
430  	   SCIP_SET*             set,                /**< global SCIP settings */
431  	   SCIP_PRIMAL*          primal              /**< primal data */
432  	   )
433  	{  /*lint --e{715}*/
434  	   SCIP_REALARRAY* tmpvals;
435  	   SCIP_BOOLARRAY* tmpvalid;
436  	   SCIP_SOL* tsol;
437  	
438  	   assert(sol != NULL);
439  	   assert(transsol != NULL);
440  	   assert(set != NULL);
441  	   assert(SCIPsolIsOriginal(sol));
442  	   assert(sol->primalindex > -1);
443  	
444  	   tsol = *transsol;
445  	   assert(tsol != NULL);
446  	   assert(!SCIPsolIsOriginal(tsol));
447  	
448  	   /* switch vals and valid arrays; the exisiting solution gets the arrays of the transformed solution;
449  	    * the transformed one gets the original arrays, because they have to be freed anyway and freeing the transsol
450  	    * automatically frees its arrays
451  	    */
452  	   tmpvals = sol->vals;
453  	   tmpvalid = sol->valid;
454  	   sol->vals = tsol->vals;
455  	   sol->valid = tsol->valid;
456  	   tsol->vals = tmpvals;
457  	   tsol->valid = tmpvalid;
458  	
459  	   /* copy solorigin and objective (should be the same, only to avoid numerical issues);
460  	    * we keep the other statistics of the original solution, since that was the first time that this solution as found
461  	    */
462  	   sol->solorigin = tsol->solorigin;
463  	   sol->obj = tsol->obj;
464  	
465  	   SCIP_CALL( SCIPsolFree(transsol, blkmem, primal) );
466  	
467  	   return SCIP_OKAY;
468  	}
469  	
470  	/** adjusts solution values of implicit integer variables in handed solution. Solution objective value is not
471  	 *  deteriorated by this method.
472  	 */
473  	SCIP_RETCODE SCIPsolAdjustImplicitSolVals(
474  	   SCIP_SOL*             sol,                /**< primal CIP solution */
475  	   SCIP_SET*             set,                /**< global SCIP settings */
476  	   SCIP_STAT*            stat,               /**< problem statistics data */
477  	   SCIP_PROB*            prob,               /**< either original or transformed problem, depending on sol origin */
478  	   SCIP_TREE*            tree,               /**< branch and bound tree */
479  	   SCIP_Bool             uselprows           /**< should LP row information be considered for none-objective variables */
480  	   )
481  	{
482  	   SCIP_VAR** vars;
483  	   int nimplvars;
484  	   int nbinvars;
485  	   int nintvars;
486  	   int v;
487  	
488  	   assert(sol != NULL);
489  	   assert(prob != NULL);
490  	
491  	   /* get variable data */
492  	   vars = SCIPprobGetVars(prob);
493  	   nbinvars = SCIPprobGetNBinVars(prob);
494  	   nintvars = SCIPprobGetNIntVars(prob);
495  	   nimplvars = SCIPprobGetNImplVars(prob);
496  	
497  	   if( nimplvars == 0 )
498  	      return SCIP_OKAY;
499  	
500  	   /* calculate the last array position of implicit integer variables */
501  	   nimplvars = nbinvars + nintvars + nimplvars;
502  	
503  	   /* loop over implicit integer variables and round them up or down */
504  	   for( v = nbinvars + nintvars; v < nimplvars; ++v )
505  	   {
506  	      SCIP_VAR* var;
507  	      SCIP_Real solval;
508  	      SCIP_Real obj;
509  	      SCIP_Real newsolval;
510  	      SCIP_Bool roundup;
511  	      SCIP_Bool rounddown;
512  	      int nuplocks;
513  	      int ndownlocks;
514  	
515  	      var = vars[v];
516  	
517  	      assert( SCIPvarGetType(var) == SCIP_VARTYPE_IMPLINT );
518  	      solval = SCIPsolGetVal(sol, set, stat, var);
519  	
520  	      /* we do not need to round integral solution values or those of variables which are not column variables */
521  	      if( SCIPsetIsFeasIntegral(set, solval) || SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
522  	         continue;
523  	
524  	      nuplocks = SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
525  	      ndownlocks = SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL);
526  	      obj = SCIPvarGetUnchangedObj(var);
527  	
528  	      roundup = FALSE;
529  	      rounddown = FALSE;
530  	
531  	      /* in case of a non-zero objective coefficient, there is only one possible rounding direction */
532  	      if( SCIPsetIsFeasNegative(set, obj) )
533  	         roundup = TRUE;
534  	      else if( SCIPsetIsFeasPositive(set, obj) )
535  	         rounddown = TRUE;
536  	      else if( uselprows )
537  	      {
538  	         /* determine rounding direction based on row violations */
539  	         SCIP_COL* col;
540  	         SCIP_ROW** rows;
541  	         SCIP_Real* vals;
542  	         int nrows;
543  	         int r;
544  	
545  	         col = SCIPvarGetCol(var);
546  	         vals = SCIPcolGetVals(col);
547  	         rows = SCIPcolGetRows(col);
548  	         nrows = SCIPcolGetNNonz(col);
549  	
550  	         /* loop over rows and search for equations whose violation can be decreased by rounding */
551  	         for( r = 0; r < nrows && !(roundup && rounddown); ++r )
552  	         {
553  	            SCIP_ROW* row;
554  	            SCIP_Real activity;
555  	            SCIP_Real rhs;
556  	            SCIP_Real lhs;
557  	
558  	            row = rows[r];
559  	
560  	            if( SCIProwIsLocal(row) || !SCIProwIsInLP(row) )
561  	               continue;
562  	
563  	            rhs = SCIProwGetRhs(row);
564  	            lhs = SCIProwGetLhs(row);
565  	
566  	            if( SCIPsetIsInfinity(set, rhs) || SCIPsetIsInfinity(set, -lhs) )
567  	               continue;
568  	
569  	            activity = SCIProwGetSolActivity(row, set, stat, sol);
570  	            if( SCIPsetIsFeasLE(set, activity, rhs) && SCIPsetIsFeasLE(set, lhs, activity) )
571  	               continue;
572  	
573  	            assert(! SCIPsetIsZero(set, vals[r]));
574  	            if( (SCIPsetIsFeasGT(set, activity, rhs) && SCIPsetIsPositive(set, vals[r]))
575  	                  || (SCIPsetIsFeasLT(set, activity, lhs) && SCIPsetIsNegative(set, vals[r])) )
576  	               rounddown = TRUE;
577  	            else
578  	               roundup = TRUE;
579  	         }
580  	      }
581  	
582  	      /* in case of a tie, we select the rounding step based on the number of variable locks */
583  	      if( roundup == rounddown )
584  	      {
585  	         rounddown = ndownlocks <= nuplocks;
586  	         roundup = !rounddown;
587  	      }
588  	
589  	      /* round the variable up or down */
590  	      if( roundup )
591  	      {
592  	         newsolval = SCIPsetCeil(set, solval);
593  	         assert(SCIPsetIsFeasLE(set, newsolval, SCIPvarGetUbGlobal(var)));
594  	      }
595  	      else
596  	      {
597  	         assert( rounddown ); /* should be true because of the code above */
598  	         newsolval = SCIPsetFloor(set, solval);
599  	         assert(SCIPsetIsFeasGE(set, newsolval, SCIPvarGetLbGlobal(var)));
600  	      }
601  	
602  	      SCIP_CALL( SCIPsolSetVal(sol, set, stat, tree, var, newsolval) );
603  	   }
604  	
605  	   return SCIP_OKAY;
606  	}
607  	/** creates primal CIP solution, initialized to the current LP solution */
608  	SCIP_RETCODE SCIPsolCreateLPSol(
609  	   SCIP_SOL**            sol,                /**< pointer to primal CIP solution */
610  	   BMS_BLKMEM*           blkmem,             /**< block memory */
611  	   SCIP_SET*             set,                /**< global SCIP settings */
612  	   SCIP_STAT*            stat,               /**< problem statistics data */
613  	   SCIP_PROB*            prob,               /**< transformed problem data */
614  	   SCIP_PRIMAL*          primal,             /**< primal data */
615  	   SCIP_TREE*            tree,               /**< branch and bound tree */
616  	   SCIP_LP*              lp,                 /**< current LP data */
617  	   SCIP_HEUR*            heur                /**< heuristic that found the solution (or NULL if it's from the tree) */
618  	   )
619  	{
620  	   assert(sol != NULL);
621  	   assert(lp != NULL);
622  	   assert(SCIPlpIsSolved(lp));
623  	
624  	   SCIP_CALL( SCIPsolCreate(sol, blkmem, set, stat, primal, tree, heur) );
625  	   SCIP_CALL( SCIPsolLinkLPSol(*sol, set, stat, prob, tree, lp) );
626  	
627  	   return SCIP_OKAY;
628  	}
629  	
630  	/** creates primal CIP solution, initialized to the current NLP solution */
631  	SCIP_RETCODE SCIPsolCreateNLPSol(
632  	   SCIP_SOL**            sol,                /**< pointer to primal CIP solution */
633  	   BMS_BLKMEM*           blkmem,             /**< block memory */
634  	   SCIP_SET*             set,                /**< global SCIP settings */
635  	   SCIP_STAT*            stat,               /**< problem statistics data */
636  	   SCIP_PRIMAL*          primal,             /**< primal data */
637  	   SCIP_TREE*            tree,               /**< branch and bound tree */
638  	   SCIP_NLP*             nlp,                /**< current NLP data */
639  	   SCIP_HEUR*            heur                /**< heuristic that found the solution (or NULL if it's from the tree) */
640  	   )
641  	{
642  	   assert(sol != NULL);
643  	   assert(nlp != NULL);
644  	
645  	   SCIP_CALL( SCIPsolCreate(sol, blkmem, set, stat, primal, tree, heur) );
646  	   SCIP_CALL( SCIPsolLinkNLPSol(*sol, stat, tree, nlp) );
647  	
648  	   return SCIP_OKAY;
649  	}
650  	
651  	/** creates primal CIP solution, initialized to the current relaxation solution */
652  	SCIP_RETCODE SCIPsolCreateRelaxSol(
653  	   SCIP_SOL**            sol,                /**< pointer to primal CIP solution */
654  	   BMS_BLKMEM*           blkmem,             /**< block memory */
655  	   SCIP_SET*             set,                /**< global SCIP settings */
656  	   SCIP_STAT*            stat,               /**< problem statistics data */
657  	   SCIP_PRIMAL*          primal,             /**< primal data */
658  	   SCIP_TREE*            tree,               /**< branch and bound tree */
659  	   SCIP_RELAXATION*      relaxation,         /**< global relaxation data */
660  	   SCIP_HEUR*            heur                /**< heuristic that found the solution (or NULL if it's from the tree) */
661  	   )
662  	{
663  	   assert(sol != NULL);
664  	   assert(relaxation != NULL);
665  	   assert(SCIPrelaxationIsSolValid(relaxation));
666  	
667  	   SCIP_CALL( SCIPsolCreate(sol, blkmem, set, stat, primal, tree, heur) );
668  	   SCIP_CALL( SCIPsolLinkRelaxSol(*sol, set, stat, tree, relaxation) );
669  	
670  	   /* update solution type and store relaxator as creator only if no heuristic is specified as creator */
671  	   if( heur == NULL )
672  	      SCIPsolSetRelax(*sol, SCIPrelaxationGetSolRelax(relaxation));
673  	
674  	   return SCIP_OKAY;
675  	}
676  	
677  	/** creates primal CIP solution, initialized to the current pseudo solution */
678  	SCIP_RETCODE SCIPsolCreatePseudoSol(
679  	   SCIP_SOL**            sol,                /**< pointer to primal CIP solution */
680  	   BMS_BLKMEM*           blkmem,             /**< block memory */
681  	   SCIP_SET*             set,                /**< global SCIP settings */
682  	   SCIP_STAT*            stat,               /**< problem statistics data */
683  	   SCIP_PROB*            prob,               /**< transformed problem data */
684  	   SCIP_PRIMAL*          primal,             /**< primal data */
685  	   SCIP_TREE*            tree,               /**< branch and bound tree, or NULL */
686  	   SCIP_LP*              lp,                 /**< current LP data */
687  	   SCIP_HEUR*            heur                /**< heuristic that found the solution (or NULL if it's from the tree) */
688  	   )
689  	{
690  	   assert(sol != NULL);
691  	
692  	   SCIP_CALL( SCIPsolCreate(sol, blkmem, set, stat, primal, tree, heur) );
693  	   SCIP_CALL( SCIPsolLinkPseudoSol(*sol, set, stat, prob, tree, lp) );
694  	
695  	   /* update solution type to pseudo solution */
696  	   if( heur == NULL )
697  	      SCIPsolSetPseudo(*sol);
698  	
699  	   return SCIP_OKAY;
700  	}
701  	
702  	/** creates primal CIP solution, initialized to the current solution */
703  	SCIP_RETCODE SCIPsolCreateCurrentSol(
704  	   SCIP_SOL**            sol,                /**< pointer to primal CIP solution */
705  	   BMS_BLKMEM*           blkmem,             /**< block memory */
706  	   SCIP_SET*             set,                /**< global SCIP settings */
707  	   SCIP_STAT*            stat,               /**< problem statistics data */
708  	   SCIP_PROB*            prob,               /**< transformed problem data */
709  	   SCIP_PRIMAL*          primal,             /**< primal data */
710  	   SCIP_TREE*            tree,               /**< branch and bound tree */
711  	   SCIP_LP*              lp,                 /**< current LP data */
712  	   SCIP_HEUR*            heur                /**< heuristic that found the solution (or NULL if it's from the tree) */
713  	   )
714  	{
715  	   assert(tree != NULL);
716  	
717  	   if( SCIPtreeHasCurrentNodeLP(tree) )
718  	   {
719  	      SCIP_CALL( SCIPsolCreateLPSol(sol, blkmem, set, stat, prob, primal, tree, lp, heur) );
720  	   }
721  	   else
722  	   {
723  	      SCIP_CALL( SCIPsolCreatePseudoSol(sol, blkmem, set, stat, prob, primal, tree, lp, heur) );
724  	   }
725  	
726  	   return SCIP_OKAY;
727  	}
728  	
729  	/** creates partial primal CIP solution, initialized to unknown values */
730  	SCIP_RETCODE SCIPsolCreatePartial(
731  	   SCIP_SOL**            sol,                /**< pointer to primal CIP solution */
732  	   BMS_BLKMEM*           blkmem,             /**< block memory */
733  	   SCIP_SET*             set,                /**< global SCIP settings */
734  	   SCIP_STAT*            stat,               /**< problem statistics data */
735  	   SCIP_PRIMAL*          primal,             /**< primal data */
736  	   SCIP_HEUR*            heur                /**< heuristic that found the solution (or NULL if it's from the tree) */
737  	   )
738  	{
739  	   assert(sol != NULL);
740  	   assert(blkmem != NULL);
741  	   assert(set != NULL);
742  	   assert(stat != NULL);
743  	   assert(primal != NULL);
744  	
745  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, sol) );
746  	   SCIP_CALL( SCIPrealarrayCreate(&(*sol)->vals, blkmem) );
747  	   SCIP_CALL( SCIPboolarrayCreate(&(*sol)->valid, blkmem) );
748  	   (*sol)->solorigin = SCIP_SOLORIGIN_PARTIAL;
749  	   (*sol)->obj = SCIP_UNKNOWN;
750  	   (*sol)->primalindex = -1;
751  	   (*sol)->index = stat->solindex;
752  	   (*sol)->hasinfval = FALSE;
753  	   stat->solindex++;
754  	   solStamp(*sol, stat, NULL, TRUE);
755  	   SCIPsolResetViolations(*sol);
756  	
757  	   /* set solution type and creator depending on whether a heuristic or NULL is passed */
758  	   SCIPsolSetHeur(*sol, heur);
759  	
760  	   SCIP_CALL( SCIPprimalSolCreated(primal, set, *sol) );
761  	
762  	   return SCIP_OKAY;
763  	}
764  	
765  	/** creates primal CIP solution, initialized to unknown values */
766  	SCIP_RETCODE SCIPsolCreateUnknown(
767  	   SCIP_SOL**            sol,                /**< pointer to primal CIP solution */
768  	   BMS_BLKMEM*           blkmem,             /**< block memory */
769  	   SCIP_SET*             set,                /**< global SCIP settings */
770  	   SCIP_STAT*            stat,               /**< problem statistics data */
771  	   SCIP_PRIMAL*          primal,             /**< primal data */
772  	   SCIP_TREE*            tree,               /**< branch and bound tree */
773  	   SCIP_HEUR*            heur                /**< heuristic that found the solution (or NULL if it's from the tree) */
774  	   )
775  	{
776  	   assert(sol != NULL);
777  	   assert(blkmem != NULL);
778  	   assert(stat != NULL);
779  	
780  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, sol) );
781  	   SCIP_CALL( SCIPrealarrayCreate(&(*sol)->vals, blkmem) );
782  	   SCIP_CALL( SCIPboolarrayCreate(&(*sol)->valid, blkmem) );
783  	   (*sol)->solorigin = SCIP_SOLORIGIN_UNKNOWN;
784  	   (*sol)->obj = 0.0;
785  	   (*sol)->primalindex = -1;
786  	   (*sol)->index = stat->solindex;
787  	   (*sol)->hasinfval = FALSE;
788  	   stat->solindex++;
789  	   solStamp(*sol, stat, tree, TRUE);
790  	   SCIPsolResetViolations(*sol);
791  	
792  	   /* set solution type and creator depending on whether a heuristic or NULL is passed */
793  	   SCIPsolSetHeur(*sol, heur);
794  	
795  	   SCIP_CALL( SCIPprimalSolCreated(primal, set, *sol) );
796  	
797  	   return SCIP_OKAY;
798  	}
799  	
800  	/** frees primal CIP solution */
801  	SCIP_RETCODE SCIPsolFree(
802  	   SCIP_SOL**            sol,                /**< pointer to primal CIP solution */
803  	   BMS_BLKMEM*           blkmem,             /**< block memory */
804  	   SCIP_PRIMAL*          primal              /**< primal data */
805  	   )
806  	{
807  	   assert(sol != NULL);
808  	   assert(*sol != NULL);
809  	
810  	   SCIPprimalSolFreed(primal, *sol);
811  	
812  	   SCIP_CALL( SCIPrealarrayFree(&(*sol)->vals) );
813  	   SCIP_CALL( SCIPboolarrayFree(&(*sol)->valid) );
814  	   BMSfreeBlockMemory(blkmem, sol);
815  	
816  	   return SCIP_OKAY;
817  	}
818  	
819  	/** copies current LP solution into CIP solution by linking */
820  	SCIP_RETCODE SCIPsolLinkLPSol(
821  	   SCIP_SOL*             sol,                /**< primal CIP solution */
822  	   SCIP_SET*             set,                /**< global SCIP settings */
823  	   SCIP_STAT*            stat,               /**< problem statistics data */
824  	   SCIP_PROB*            prob,               /**< transformed problem data */
825  	   SCIP_TREE*            tree,               /**< branch and bound tree */
826  	   SCIP_LP*              lp                  /**< current LP data */
827  	   )
828  	{
829  	   assert(sol != NULL);
830  	   assert(stat != NULL);
831  	   assert(tree != NULL);
832  	   assert(lp != NULL);
833  	   assert(lp->solved);
834  	   assert(SCIPlpDiving(lp) || SCIPtreeProbing(tree) || !SCIPlpDivingObjChanged(lp));
835  	
836  	   SCIPsetDebugMsg(set, "linking solution to LP\n");
837  	
838  	   /* clear the old solution arrays */
839  	   SCIP_CALL( solClearArrays(sol) );
840  	
841  	   /* link solution to LP solution */
842  	   if( SCIPlpDivingObjChanged(lp) )
843  	   {
844  	      /* the objective value has to be calculated manually, because the LP's value is invalid;
845  	       * use objective values of variables, because columns objective values are changed to dive values
846  	       */
847  	      sol->obj = SCIPlpGetLooseObjval(lp, set, prob);
848  	      if( !SCIPsetIsInfinity(set, -sol->obj) )
849  	      {
850  	         SCIP_VAR* var;
851  	         SCIP_COL** cols;
852  	         int ncols;
853  	         int c;
854  	
855  	         cols = SCIPlpGetCols(lp);
856  	         ncols = SCIPlpGetNCols(lp);
857  	         for( c = 0; c < ncols; ++c )
858  	         {
859  	            var = SCIPcolGetVar(cols[c]);
860  	            sol->obj += SCIPvarGetUnchangedObj(var) * cols[c]->primsol;
861  	         }
862  	      }
863  	   }
864  	   else
865  	   {
866  	      /* the objective value in the columns is correct, s.t. the LP's objective value is also correct */
867  	      sol->obj = SCIPlpGetObjval(lp, set, prob);
868  	   }
869  	   sol->solorigin = SCIP_SOLORIGIN_LPSOL;
870  	   solStamp(sol, stat, tree, TRUE);
871  	
872  	   SCIPsetDebugMsg(set, " -> objective value: %g\n", sol->obj);
873  	
874  	   return SCIP_OKAY;
875  	}
876  	
877  	/** copies current NLP solution into CIP solution by linking */
878  	SCIP_RETCODE SCIPsolLinkNLPSol(
879  	   SCIP_SOL*             sol,                /**< primal CIP solution */
880  	   SCIP_STAT*            stat,               /**< problem statistics data */
881  	   SCIP_TREE*            tree,               /**< branch and bound tree */
882  	   SCIP_NLP*             nlp                 /**< current NLP data */
883  	   )
884  	{
885  	   assert(sol != NULL);
886  	   assert(stat != NULL);
887  	   assert(tree != NULL);
888  	   assert(nlp != NULL);
889  	   assert(SCIPnlpHasSolution(nlp));
890  	
891  	   SCIPstatDebugMsg(stat, "linking solution to NLP\n");
892  	
893  	   /* clear the old solution arrays */
894  	   SCIP_CALL( solClearArrays(sol) );
895  	
896  	   /* get objective value of NLP solution */
897  	   if( SCIPnlpIsDivingObjChanged(nlp) )
898  	   {
899  	      /* the objective value has to be calculated manually, because the NLP's value is invalid */
900  	
901  	      SCIP_VAR** vars;
902  	      int nvars;
903  	      int v;
904  	
905  	      sol->obj = 0.0;
906  	
907  	      vars = SCIPnlpGetVars(nlp);
908  	      nvars = SCIPnlpGetNVars(nlp);
909  	      for( v = 0; v < nvars; ++v )
910  	      {
911  	         assert(SCIPvarIsActive(vars[v]));
912  	         sol->obj += SCIPvarGetUnchangedObj(vars[v]) * SCIPvarGetNLPSol(vars[v]);
913  	      }
914  	   }
915  	   else
916  	   {
917  	      sol->obj = SCIPnlpGetObjval(nlp);
918  	   }
919  	
920  	   sol->solorigin = SCIP_SOLORIGIN_NLPSOL;
921  	   solStamp(sol, stat, tree, TRUE);
922  	
923  	   SCIPstatDebugMsg(stat, " -> objective value: %g\n", sol->obj);
924  	
925  	   return SCIP_OKAY;
926  	}
927  	
928  	/** copies current relaxation solution into CIP solution by linking */
929  	SCIP_RETCODE SCIPsolLinkRelaxSol(
930  	   SCIP_SOL*             sol,                /**< primal CIP solution */
931  	   SCIP_SET*             set,                /**< global SCIP settings */
932  	   SCIP_STAT*            stat,               /**< problem statistics data */
933  	   SCIP_TREE*            tree,               /**< branch and bound tree */
934  	   SCIP_RELAXATION*      relaxation          /**< global relaxation data */
935  	   )
936  	{  /*lint --e{715}*/
937  	   assert(sol != NULL);
938  	   assert(stat != NULL);
939  	   assert(tree != NULL);
940  	   assert(relaxation != NULL);
941  	   assert(SCIPrelaxationIsSolValid(relaxation));
942  	
943  	   SCIPsetDebugMsg(set, "linking solution to relaxation\n");
944  	
945  	   /* clear the old solution arrays */
946  	   SCIP_CALL( solClearArrays(sol) );
947  	
948  	   /* the objective value in the columns is correct, s.t. the LP's objective value is also correct */
949  	   sol->obj = SCIPrelaxationGetSolObj(relaxation);
950  	   sol->solorigin = SCIP_SOLORIGIN_RELAXSOL;
951  	   solStamp(sol, stat, tree, TRUE);
952  	
953  	   SCIPsetDebugMsg(set, " -> objective value: %g\n", sol->obj);
954  	
955  	   return SCIP_OKAY;
956  	}
957  	
958  	/** copies current pseudo solution into CIP solution by linking */
959  	SCIP_RETCODE SCIPsolLinkPseudoSol(
960  	   SCIP_SOL*             sol,                /**< primal CIP solution */
961  	   SCIP_SET*             set,                /**< global SCIP settings */
962  	   SCIP_STAT*            stat,               /**< problem statistics data */
963  	   SCIP_PROB*            prob,               /**< transformed problem data */
964  	   SCIP_TREE*            tree,               /**< branch and bound tree, or NULL */
965  	   SCIP_LP*              lp                  /**< current LP data */
966  	   )
967  	{
968  	   assert(sol != NULL);
969  	   assert(stat != NULL);
970  	   assert(tree != NULL);
971  	
972  	   SCIPsetDebugMsg(set, "linking solution to pseudo solution\n");
973  	
974  	   /* clear the old solution arrays */
975  	   SCIP_CALL( solClearArrays(sol) );
976  	
977  	   /* link solution to pseudo solution */
978  	   sol->obj = SCIPlpGetPseudoObjval(lp, set, prob);
979  	   sol->solorigin = SCIP_SOLORIGIN_PSEUDOSOL;
980  	   solStamp(sol, stat, tree, TRUE);
981  	
982  	   SCIPsetDebugMsg(set, " -> objective value: %g\n", sol->obj);
983  	
984  	   return SCIP_OKAY;
985  	}
986  	
987  	/** copies current solution (LP or pseudo solution) into CIP solution by linking */
988  	SCIP_RETCODE SCIPsolLinkCurrentSol(
989  	   SCIP_SOL*             sol,                /**< primal CIP solution */
990  	   SCIP_SET*             set,                /**< global SCIP settings */
991  	   SCIP_STAT*            stat,               /**< problem statistics data */
992  	   SCIP_PROB*            prob,               /**< transformed problem data */
993  	   SCIP_TREE*            tree,               /**< branch and bound tree */
994  	   SCIP_LP*              lp                  /**< current LP data */
995  	   )
996  	{
997  	   assert(tree != NULL);
998  	
999  	   SCIPsetDebugMsg(set, "linking solution to current solution\n");
1000 	
1001 	   if( SCIPtreeHasCurrentNodeLP(tree) && SCIPlpIsSolved(lp) )
1002 	   {
1003 	      SCIP_CALL( SCIPsolLinkLPSol(sol, set, stat, prob, tree, lp) );
1004 	   }
1005 	   else
1006 	   {
1007 	      SCIP_CALL( SCIPsolLinkPseudoSol(sol, set, stat, prob, tree, lp) );
1008 	   }
1009 	
1010 	   return SCIP_OKAY;
1011 	}
1012 	
1013 	/** clears primal CIP solution */
1014 	SCIP_RETCODE SCIPsolClear(
1015 	   SCIP_SOL*             sol,                /**< primal CIP solution */
1016 	   SCIP_STAT*            stat,               /**< problem statistics data */
1017 	   SCIP_TREE*            tree                /**< branch and bound tree */
1018 	   )
1019 	{
1020 	   assert(sol != NULL);
1021 	
1022 	   SCIP_CALL( solClearArrays(sol) );
1023 	   sol->solorigin = SCIP_SOLORIGIN_ZERO;
1024 	   sol->obj = 0.0;
1025 	   solStamp(sol, stat, tree, TRUE);
1026 	
1027 	   return SCIP_OKAY;
1028 	}
1029 	
1030 	/** declares all entries in the primal CIP solution to be unknown */
1031 	SCIP_RETCODE SCIPsolSetUnknown(
1032 	   SCIP_SOL*             sol,                /**< primal CIP solution */
1033 	   SCIP_STAT*            stat,               /**< problem statistics data */
1034 	   SCIP_TREE*            tree                /**< branch and bound tree */
1035 	   )
1036 	{
1037 	   assert(sol != NULL);
1038 	
1039 	   SCIP_CALL( solClearArrays(sol) );
1040 	   sol->solorigin = SCIP_SOLORIGIN_UNKNOWN;
1041 	   sol->obj = 0.0;
1042 	   solStamp(sol, stat, tree, TRUE);
1043 	
1044 	   return SCIP_OKAY;
1045 	}
1046 	
1047 	/** stores solution values of variables in solution's own array */
1048 	SCIP_RETCODE SCIPsolUnlink(
1049 	   SCIP_SOL*             sol,                /**< primal CIP solution */
1050 	   SCIP_SET*             set,                /**< global SCIP settings */
1051 	   SCIP_PROB*            prob                /**< transformed problem data */
1052 	   )
1053 	{
1054 	   int v;
1055 	
1056 	   assert(sol != NULL);
1057 	   assert(prob != NULL);
1058 	   assert(prob->nvars == 0 || prob->vars != NULL);
1059 	
1060 	   if( !SCIPsolIsOriginal(sol) && sol->solorigin != SCIP_SOLORIGIN_ZERO
1061 	      && sol->solorigin != SCIP_SOLORIGIN_UNKNOWN )
1062 	   {
1063 	      SCIPsetDebugMsg(set, "completing solution %p\n", (void*)sol);
1064 	
1065 	      for( v = 0; v < prob->nvars; ++v )
1066 	      {
1067 	         SCIP_CALL( solUnlinkVar(sol, set, prob->vars[v]) );
1068 	      }
1069 	
1070 	      sol->solorigin = SCIP_SOLORIGIN_ZERO;
1071 	   }
1072 	
1073 	   return SCIP_OKAY;
1074 	}
1075 	
1076 	/** sets value of variable in primal CIP solution */
1077 	SCIP_RETCODE SCIPsolSetVal(
1078 	   SCIP_SOL*             sol,                /**< primal CIP solution */
1079 	   SCIP_SET*             set,                /**< global SCIP settings */
1080 	   SCIP_STAT*            stat,               /**< problem statistics data */
1081 	   SCIP_TREE*            tree,               /**< branch and bound tree, or NULL */
1082 	   SCIP_VAR*             var,                /**< variable to add to solution */
1083 	   SCIP_Real             val                 /**< solution value of variable */
1084 	   )
1085 	{
1086 	   SCIP_Real oldval;
1087 	
1088 	   assert(sol != NULL);
1089 	   assert(stat != NULL);
1090 	   assert(sol->solorigin == SCIP_SOLORIGIN_ORIGINAL
1091 	      || sol->solorigin == SCIP_SOLORIGIN_ZERO
1092 	      || sol->solorigin == SCIP_SOLORIGIN_PARTIAL
1093 	      || sol->solorigin == SCIP_SOLORIGIN_UNKNOWN
1094 	      || (sol->nodenum == stat->nnodes && sol->runnum == stat->nruns));
1095 	   assert(var != NULL);
1096 	   assert(SCIPisFinite(val));
1097 	
1098 	   SCIPsetDebugMsg(set, "setting value of <%s> in solution %p to %g\n", SCIPvarGetName(var), (void*)sol, val);
1099 	
1100 	   /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
1101 	   switch( SCIPvarGetStatus(var) )
1102 	   {
1103 	   case SCIP_VARSTATUS_ORIGINAL:
1104 	      if( SCIPsolIsOriginal(sol) )
1105 	      {
1106 	         oldval = solGetArrayVal(sol, var);
1107 	
1108 	         if( val != oldval )  /*lint !e777*/
1109 	         {
1110 	            SCIP_CALL( solSetArrayVal(sol, set, var, val) );
1111 	
1112 	            /* update the objective value; we do not need to do this for invalid objectives or partial solutions */
1113 	            if( sol->obj != SCIP_INVALID && !SCIPsolIsPartial(sol) ) /*lint !e777*/
1114 	            {
1115 	               SCIP_Real obj;
1116 	               SCIP_Real oldobjcont;
1117 	               SCIP_Real newobjcont;
1118 	
1119 	               /* an unknown solution value does not count towards the objective */
1120 	               obj = SCIPvarGetUnchangedObj(var);
1121 	               oldobjcont = (oldval == SCIP_UNKNOWN ? 0.0 : obj * oldval); /*lint !e777*/
1122 	               newobjcont = (val == SCIP_UNKNOWN ? 0.0 : obj * val); /*lint !e777*/
1123 	
1124 	               /* we want to use a safe invalid if the contribution exchange contradicts the infinity status of the objective value */
1125 	               if( SCIPsetIsInfinity(set, sol->obj) )
1126 	               {
1127 	                  if( ( SCIPsetIsInfinity(set, oldobjcont) && !SCIPsetIsInfinity(set, newobjcont) )
1128 	                     || ( !SCIPsetIsInfinity(set, -oldobjcont) && SCIPsetIsInfinity(set, -newobjcont) ) )
1129 	                     sol->obj = SCIP_INVALID;
1130 	               }
1131 	               else if( SCIPsetIsInfinity(set, -sol->obj) )
1132 	               {
1133 	                  if( ( SCIPsetIsInfinity(set, -oldobjcont) && !SCIPsetIsInfinity(set, -newobjcont) )
1134 	                     || ( !SCIPsetIsInfinity(set, oldobjcont) && SCIPsetIsInfinity(set, newobjcont) ) )
1135 	                     sol->obj = SCIP_INVALID;
1136 	               }
1137 	               /* we want to use a clean infinity if the contribution exchange or the resulting objective hits the infinity bound */
1138 	               else
1139 	               {
1140 	                  if( !SCIPsetIsInfinity(set, MAX(ABS(oldobjcont), ABS(newobjcont))) )
1141 	                  {
1142 	                     sol->obj -= oldobjcont;
1143 	                     sol->obj += newobjcont;
1144 	
1145 	                     if( SCIPsetIsInfinity(set, sol->obj) )
1146 	                        sol->obj = SCIPsetInfinity(set);
1147 	                     else if( SCIPsetIsInfinity(set, -sol->obj) )
1148 	                        sol->obj = -SCIPsetInfinity(set);
1149 	                  }
1150 	                  else if( !SCIPsetIsInfinity(set, MAX(oldobjcont, -newobjcont)) )
1151 	                     sol->obj = SCIPsetInfinity(set);
1152 	                  else if( !SCIPsetIsInfinity(set, MAX(-oldobjcont, newobjcont)) )
1153 	                     sol->obj = -SCIPsetInfinity(set);
1154 	               }
1155 	            }
1156 	
1157 	            solStamp(sol, stat, tree, FALSE);
1158 	         }
1159 	         return SCIP_OKAY;
1160 	      }
1161 	      else
1162 	         return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetTransVar(var), val);
1163 	
1164 	   case SCIP_VARSTATUS_LOOSE:
1165 	   case SCIP_VARSTATUS_COLUMN:
1166 	      assert(!SCIPsolIsOriginal(sol));
1167 	      assert(sol->solorigin != SCIP_SOLORIGIN_LPSOL || SCIPboolarrayGetVal(sol->valid, SCIPvarGetIndex(var))
1168 	         || sol->lpcount == stat->lpcount);
1169 	      oldval = solGetArrayVal(sol, var);
1170 	      if( val != oldval )  /*lint !e777*/
1171 	      {
1172 	         SCIP_CALL( solSetArrayVal(sol, set, var, val) );
1173 	
1174 	         /* update the objective value; we do not need to do this for invalid objectives */
1175 	         if( sol->obj != SCIP_INVALID ) /*lint !e777*/
1176 	         {
1177 	            SCIP_Real obj;
1178 	            SCIP_Real oldobjcont;
1179 	            SCIP_Real newobjcont;
1180 	
1181 	            /* an unknown solution value does not count towards the objective */
1182 	            obj = SCIPvarGetUnchangedObj(var);
1183 	            oldobjcont = (oldval == SCIP_UNKNOWN ? 0.0 : obj * oldval); /*lint !e777*/
1184 	            newobjcont = (val == SCIP_UNKNOWN ? 0.0 : obj * val); /*lint !e777*/
1185 	
1186 	            /* we want to use a safe invalid if the contribution exchange contradicts the infinity status of the objective value */
1187 	            if( SCIPsetIsInfinity(set, sol->obj) )
1188 	            {
1189 	               if( ( SCIPsetIsInfinity(set, oldobjcont) && !SCIPsetIsInfinity(set, newobjcont) )
1190 	                  || ( !SCIPsetIsInfinity(set, -oldobjcont) && SCIPsetIsInfinity(set, -newobjcont) ) )
1191 	                  sol->obj = SCIP_INVALID;
1192 	            }
1193 	            else if( SCIPsetIsInfinity(set, -sol->obj) )
1194 	            {
1195 	               if( ( SCIPsetIsInfinity(set, -oldobjcont) && !SCIPsetIsInfinity(set, -newobjcont) )
1196 	                  || ( !SCIPsetIsInfinity(set, oldobjcont) && SCIPsetIsInfinity(set, newobjcont) ) )
1197 	                  sol->obj = SCIP_INVALID;
1198 	            }
1199 	            /* we want to use a clean infinity if the contribution exchange or the resulting objective hits the infinity bound */
1200 	            else
1201 	            {
1202 	               if( !SCIPsetIsInfinity(set, MAX(ABS(oldobjcont), ABS(newobjcont))) )
1203 	               {
1204 	                  sol->obj -= oldobjcont;
1205 	                  sol->obj += newobjcont;
1206 	
1207 	                  if( SCIPsetIsInfinity(set, sol->obj) )
1208 	                     sol->obj = SCIPsetInfinity(set);
1209 	                  else if( SCIPsetIsInfinity(set, -sol->obj) )
1210 	                     sol->obj = -SCIPsetInfinity(set);
1211 	               }
1212 	               else if( !SCIPsetIsInfinity(set, MAX(oldobjcont, -newobjcont)) )
1213 	                  sol->obj = SCIPsetInfinity(set);
1214 	               else if( !SCIPsetIsInfinity(set, MAX(-oldobjcont, newobjcont)) )
1215 	                  sol->obj = -SCIPsetInfinity(set);
1216 	            }
1217 	         }
1218 	
1219 	         solStamp(sol, stat, tree, FALSE);
1220 	      }
1221 	      return SCIP_OKAY;
1222 	
1223 	   case SCIP_VARSTATUS_FIXED:
1224 	      assert(!SCIPsolIsOriginal(sol));
1225 	      oldval = SCIPvarGetLbGlobal(var);
1226 	      if( val != oldval )  /*lint !e777*/
1227 	      {
1228 	         SCIPerrorMessage("cannot set solution value for variable <%s> fixed to %.15g to different value %.15g\n",
1229 	            SCIPvarGetName(var), oldval, val);
1230 	         return SCIP_INVALIDDATA;
1231 	      }
1232 	      return SCIP_OKAY;
1233 	
1234 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  =>  y = (x-c)/a */
1235 	      assert(!SCIPsetIsZero(set, SCIPvarGetAggrScalar(var)));
1236 	      assert(!SCIPsetIsInfinity(set, SCIPvarGetAggrConstant(var)) && !SCIPsetIsInfinity(set, -SCIPvarGetAggrConstant(var)));
1237 	      assert(!SCIPsetIsInfinity(set, SCIPvarGetAggrScalar(var)) && !SCIPsetIsInfinity(set, -SCIPvarGetAggrScalar(var)));
1238 	
1239 	      if( val == SCIP_UNKNOWN )/*lint !e777*/
1240 	         return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetAggrVar(var), val);
1241 	      if( SCIPsetIsInfinity(set, val) || SCIPsetIsInfinity(set, -val) )
1242 	         return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetAggrVar(var),  SCIPvarGetAggrScalar(var) > 0 ? val : -val);
1243 	      else
1244 	         return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetAggrVar(var), (val - SCIPvarGetAggrConstant(var))/SCIPvarGetAggrScalar(var));
1245 	
1246 	   case SCIP_VARSTATUS_MULTAGGR:
1247 	      if ( SCIPvarGetMultaggrNVars(var) == 1 )
1248 	      {
1249 	         SCIP_VAR** multaggrvars;
1250 	         SCIP_Real* multaggrscalars;
1251 	         SCIP_Real multaggrconstant;
1252 	
1253 	         multaggrvars = SCIPvarGetMultaggrVars(var);
1254 	         multaggrscalars = SCIPvarGetMultaggrScalars(var);
1255 	         multaggrconstant = SCIPvarGetMultaggrConstant(var);
1256 	
1257 	         if( SCIPsetIsInfinity(set, multaggrconstant) || SCIPsetIsInfinity(set, -multaggrconstant) )
1258 	         {
1259 	            if( (SCIPsetIsInfinity(set, multaggrconstant) && !SCIPsetIsInfinity(set, val))
1260 	               || (SCIPsetIsInfinity(set, -multaggrconstant) && !SCIPsetIsInfinity(set, -val)) )
1261 	            {
1262 	               SCIPerrorMessage("cannot set solution value for variable <%s> fixed to %.15g to different value %.15g\n",
1263 	                  SCIPvarGetName(var), multaggrconstant, val);
1264 	               return SCIP_INVALIDDATA;
1265 	            }
1266 	            return SCIP_OKAY;
1267 	         }
1268 	         else
1269 	         {
1270 	            if( SCIPsetIsInfinity(set, val) || SCIPsetIsInfinity(set, -val) )
1271 	               return SCIPsolSetVal(sol, set, stat, tree, multaggrvars[0],  multaggrscalars[0] > 0 ? val : -val);
1272 	            else
1273 	               return SCIPsolSetVal(sol, set, stat, tree, multaggrvars[0], (val - multaggrconstant)/multaggrscalars[0]);
1274 	         }
1275 	      }
1276 	      SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
1277 	      return SCIP_INVALIDDATA;
1278 	
1279 	   case SCIP_VARSTATUS_NEGATED:
1280 	      assert(!SCIPsetIsInfinity(set, SCIPvarGetNegationConstant(var)) && !SCIPsetIsInfinity(set, -SCIPvarGetNegationConstant(var)));
1281 	
1282 	      if( val == SCIP_UNKNOWN )/*lint !e777*/
1283 	         return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetNegationVar(var), val);
1284 	      else if( SCIPsetIsInfinity(set, val) || SCIPsetIsInfinity(set, -val) )
1285 	         return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetNegationVar(var), -val);
1286 	      else
1287 	         return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetNegationVar(var), SCIPvarGetNegationConstant(var) - val);
1288 	
1289 	   default:
1290 	      SCIPerrorMessage("unknown variable status\n");
1291 	      return SCIP_INVALIDDATA;
1292 	   }
1293 	}
1294 	
1295 	/** increases value of variable in primal CIP solution */
1296 	SCIP_RETCODE SCIPsolIncVal(
1297 	   SCIP_SOL*             sol,                /**< primal CIP solution */
1298 	   SCIP_SET*             set,                /**< global SCIP settings */
1299 	   SCIP_STAT*            stat,               /**< problem statistics data */
1300 	   SCIP_TREE*            tree,               /**< branch and bound tree */
1301 	   SCIP_VAR*             var,                /**< variable to increase solution value for */
1302 	   SCIP_Real             incval              /**< increment for solution value of variable */
1303 	   )
1304 	{
1305 	   SCIP_Real oldval;
1306 	
1307 	   assert(sol != NULL);
1308 	   assert(stat != NULL);
1309 	   assert(sol->solorigin == SCIP_SOLORIGIN_ORIGINAL
1310 	      || sol->solorigin == SCIP_SOLORIGIN_ZERO
1311 	      || (sol->nodenum == stat->nnodes && sol->runnum == stat->nruns));
1312 	   assert(var != NULL);
1313 	   assert(!SCIPsetIsInfinity(set, incval) && !SCIPsetIsInfinity(set, -incval));
1314 	
1315 	   SCIPsetDebugMsg(set, "increasing value of <%s> in solution %p by %g\n", SCIPvarGetName(var), (void*)sol, incval);
1316 	
1317 	   if( incval == 0.0 )
1318 	      return SCIP_OKAY;
1319 	
1320 	   assert(sol->solorigin != SCIP_SOLORIGIN_LPSOL || SCIPboolarrayGetVal(sol->valid, SCIPvarGetIndex(var))
1321 	      || sol->lpcount == stat->lpcount);
1322 	
1323 	   oldval = solGetArrayVal(sol, var);
1324 	   if( SCIPsetIsInfinity(set, oldval) || SCIPsetIsInfinity(set, -oldval) )
1325 	      return SCIP_OKAY;
1326 	
1327 	   /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
1328 	   /* @todo: handle strange cases, such as sums that yield infinite values */
1329 	   switch( SCIPvarGetStatus(var) )
1330 	   {
1331 	   case SCIP_VARSTATUS_ORIGINAL:
1332 	      if( SCIPsolIsOriginal(sol) )
1333 	      {
1334 	         SCIP_CALL( solIncArrayVal(sol, set, var, incval) );
1335 	         sol->obj += SCIPvarGetUnchangedObj(var) * incval;
1336 	         solStamp(sol, stat, tree, FALSE);
1337 	         return SCIP_OKAY;
1338 	      }
1339 	      else
1340 	         return SCIPsolIncVal(sol, set, stat, tree, SCIPvarGetTransVar(var), incval);
1341 	
1342 	   case SCIP_VARSTATUS_LOOSE:
1343 	   case SCIP_VARSTATUS_COLUMN:
1344 	      assert(!SCIPsolIsOriginal(sol));
1345 	      SCIP_CALL( solIncArrayVal(sol, set, var, incval) );
1346 	      sol->obj += SCIPvarGetUnchangedObj(var) * incval;
1347 	      solStamp(sol, stat, tree, FALSE);
1348 	      return SCIP_OKAY;
1349 	
1350 	   case SCIP_VARSTATUS_FIXED:
1351 	      SCIPerrorMessage("cannot increase solution value for fixed variable\n");
1352 	      return SCIP_INVALIDDATA;
1353 	
1354 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  =>  y = (x-c)/a */
1355 	      assert(!SCIPsetIsZero(set, SCIPvarGetAggrScalar(var)));
1356 	      return SCIPsolIncVal(sol, set, stat, tree, SCIPvarGetAggrVar(var), incval/SCIPvarGetAggrScalar(var));
1357 	
1358 	   case SCIP_VARSTATUS_MULTAGGR:
1359 	      SCIPerrorMessage("cannot increase solution value for multiple aggregated variable\n");
1360 	      return SCIP_INVALIDDATA;
1361 	
1362 	   case SCIP_VARSTATUS_NEGATED:
1363 	      return SCIPsolIncVal(sol, set, stat, tree, SCIPvarGetNegationVar(var), -incval);
1364 	
1365 	   default:
1366 	      SCIPerrorMessage("unknown variable status\n");
1367 	      return SCIP_INVALIDDATA;
1368 	   }
1369 	}
1370 	
1371 	/** returns value of variable in primal CIP solution */
1372 	SCIP_Real SCIPsolGetVal(
1373 	   SCIP_SOL*             sol,                /**< primal CIP solution */
1374 	   SCIP_SET*             set,                /**< global SCIP settings */
1375 	   SCIP_STAT*            stat,               /**< problem statistics data */
1376 	   SCIP_VAR*             var                 /**< variable to get value for */
1377 	   )
1378 	{
1379 	   SCIP_VAR** vars;
1380 	   SCIP_Real* scalars;
1381 	   SCIP_Real solval;
1382 	   SCIP_Real solvalsum;
1383 	   int nvars;
1384 	   int i;
1385 	
1386 	   assert(sol != NULL);
1387 	   assert(sol->solorigin == SCIP_SOLORIGIN_ORIGINAL
1388 	      || sol->solorigin == SCIP_SOLORIGIN_ZERO
1389 	      || sol->solorigin == SCIP_SOLORIGIN_PARTIAL
1390 	      || sol->solorigin == SCIP_SOLORIGIN_UNKNOWN
1391 	      || (sol->nodenum == stat->nnodes && sol->runnum == stat->nruns));
1392 	   assert(var != NULL);
1393 	
1394 	   /* if the value of a transformed variable in an original solution is requested, we need to project the variable back
1395 	    * to the original space, the opposite case is handled below
1396 	    */
1397 	   if( SCIPsolIsOriginal(sol) && SCIPvarIsTransformed(var) )
1398 	   {
1399 	      SCIP_RETCODE retcode;
1400 	      SCIP_VAR* origvar;
1401 	      SCIP_Real scalar;
1402 	      SCIP_Real constant;
1403 	
1404 	      /* we cannot get the value of a transformed variable for a solution that lives in the original problem space
1405 	       * -> get the corresponding original variable first
1406 	       */
1407 	      origvar = var;
1408 	      scalar = 1.0;
1409 	      constant = 0.0;
1410 	      retcode = SCIPvarGetOrigvarSum(&origvar, &scalar, &constant);
1411 	      if ( retcode != SCIP_OKAY )
1412 	         return SCIP_INVALID;
1413 	      if( origvar == NULL )
1414 	      {
1415 	         /* the variable has no original counterpart: in the original solution, it has a value of zero */
1416 	         return 0.0;
1417 	      }
1418 	      assert(!SCIPvarIsTransformed(origvar));
1419 	
1420 	      solval = SCIPsolGetVal(sol, set, stat, origvar);
1421 	      if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1422 	         return SCIP_UNKNOWN;
1423 	      else
1424 	         return scalar * solval + constant;
1425 	   }
1426 	
1427 	   /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
1428 	   switch( SCIPvarGetStatus(var) )
1429 	   {
1430 	   case SCIP_VARSTATUS_ORIGINAL:
1431 	      if( SCIPsolIsOriginal(sol) )
1432 	         return solGetArrayVal(sol, var);
1433 	      else
1434 	         return SCIPsolGetVal(sol, set, stat, SCIPvarGetTransVar(var));
1435 	
1436 	   case SCIP_VARSTATUS_LOOSE:
1437 	   case SCIP_VARSTATUS_COLUMN:
1438 	      assert(!SCIPsolIsOriginal(sol));
1439 	      assert(sol->solorigin != SCIP_SOLORIGIN_LPSOL || SCIPboolarrayGetVal(sol->valid, SCIPvarGetIndex(var))
1440 	         || sol->lpcount == stat->lpcount);
1441 	      return solGetArrayVal(sol, var);
1442 	
1443 	   case SCIP_VARSTATUS_FIXED:
1444 	      assert(!SCIPsolIsOriginal(sol));
1445 	      assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
1446 	      assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
1447 	      assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
1448 	      return SCIPvarGetLbGlobal(var);
1449 	
1450 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  =>  y = (x-c)/a */
1451 	      solval = SCIPsolGetVal(sol, set, stat, SCIPvarGetAggrVar(var));
1452 	      if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1453 	         return SCIP_UNKNOWN;
1454 	      if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
1455 	      {
1456 	         if( SCIPvarGetAggrScalar(var) * solval > 0.0 )
1457 	            return SCIPsetInfinity(set);
1458 	         if( SCIPvarGetAggrScalar(var) * solval < 0.0 )
1459 	            return -SCIPsetInfinity(set);
1460 	      }
1461 	      return SCIPvarGetAggrScalar(var) * solval + SCIPvarGetAggrConstant(var);
1462 	
1463 	   case SCIP_VARSTATUS_MULTAGGR:
1464 	      nvars = SCIPvarGetMultaggrNVars(var);
1465 	      vars = SCIPvarGetMultaggrVars(var);
1466 	      scalars = SCIPvarGetMultaggrScalars(var);
1467 	      solvalsum = SCIPvarGetMultaggrConstant(var);
1468 	      for( i = 0; i < nvars; ++i )
1469 	      {
1470 	         solval = SCIPsolGetVal(sol, set, stat, vars[i]);
1471 	         if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1472 	            return SCIP_UNKNOWN;
1473 	         if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
1474 	         {
1475 	            if( scalars[i] * solval > 0.0 )
1476 	               return SCIPsetInfinity(set);
1477 	            if( scalars[i] * solval < 0.0 )
1478 	               return -SCIPsetInfinity(set);
1479 	         }
1480 	         solvalsum += scalars[i] * solval;
1481 	      }
1482 	      return solvalsum;
1483 	
1484 	   case SCIP_VARSTATUS_NEGATED:
1485 	      solval = SCIPsolGetVal(sol, set, stat, SCIPvarGetNegationVar(var));
1486 	      if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1487 	         return SCIP_UNKNOWN;
1488 	      if( SCIPsetIsInfinity(set, solval) )
1489 	         return -SCIPsetInfinity(set);
1490 	      if( SCIPsetIsInfinity(set, -solval) )
1491 	         return SCIPsetInfinity(set);
1492 	      return SCIPvarGetNegationConstant(var) - solval;
1493 	
1494 	   default:
1495 	      SCIPerrorMessage("unknown variable status\n");
1496 	      SCIPABORT();
1497 	      return 0.0; /*lint !e527*/
1498 	   }
1499 	}
1500 	
1501 	/** returns value of variable in primal ray represented by primal CIP solution */
1502 	SCIP_Real SCIPsolGetRayVal(
1503 	   SCIP_SOL*             sol,                /**< primal CIP solution, representing a primal ray */
1504 	   SCIP_SET*             set,                /**< global SCIP settings */
1505 	   SCIP_STAT*            stat,               /**< problem statistics data */
1506 	   SCIP_VAR*             var                 /**< variable to get value for */
1507 	   )
1508 	{
1509 	   SCIP_VAR** vars;
1510 	   SCIP_Real* scalars;
1511 	   SCIP_Real solval;
1512 	   SCIP_Real solvalsum;
1513 	   int nvars;
1514 	   int i;
1515 	
1516 	   assert(sol != NULL);
1517 	   assert(sol->solorigin == SCIP_SOLORIGIN_ZERO);
1518 	   assert(var != NULL);
1519 	
1520 	   /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
1521 	   switch( SCIPvarGetStatus(var) )
1522 	   {
1523 	   case SCIP_VARSTATUS_ORIGINAL:
1524 	      return SCIPsolGetRayVal(sol, set, stat, SCIPvarGetTransVar(var));
1525 	
1526 	   case SCIP_VARSTATUS_LOOSE:
1527 	   case SCIP_VARSTATUS_COLUMN:
1528 	      return solGetArrayVal(sol, var);
1529 	
1530 	   case SCIP_VARSTATUS_FIXED:
1531 	      assert(!SCIPsolIsOriginal(sol));
1532 	      assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
1533 	      assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
1534 	      assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
1535 	      return 0.0; /* constants are ignored for computing the ray direction */
1536 	
1537 	   case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c  =>  y = (x-c)/a */
1538 	      solval = SCIPsolGetRayVal(sol, set, stat, SCIPvarGetAggrVar(var));
1539 	      assert(solval != SCIP_UNKNOWN); /*lint !e777*/
1540 	      assert(!SCIPsetIsInfinity(set, REALABS(solval)));
1541 	      return SCIPvarGetAggrScalar(var) * solval; /* constants are ignored for computing the ray direction */
1542 	
1543 	   case SCIP_VARSTATUS_MULTAGGR:
1544 	      nvars = SCIPvarGetMultaggrNVars(var);
1545 	      vars = SCIPvarGetMultaggrVars(var);
1546 	      scalars = SCIPvarGetMultaggrScalars(var);
1547 	      solvalsum = 0.0; /* constants are ignored for computing the ray direction */
1548 	      for( i = 0; i < nvars; ++i )
1549 	      {
1550 	         solval = SCIPsolGetRayVal(sol, set, stat, vars[i]);
1551 	         assert(solval != SCIP_UNKNOWN ); /*lint !e777*/
1552 	         assert(!SCIPsetIsInfinity(set, REALABS(solval)));
1553 	         solvalsum += scalars[i] * solval;
1554 	      }
1555 	      return solvalsum;
1556 	
1557 	   case SCIP_VARSTATUS_NEGATED:
1558 	      solval = SCIPsolGetRayVal(sol, set, stat, SCIPvarGetNegationVar(var));
1559 	      assert(solval != SCIP_UNKNOWN); /*lint !e777*/
1560 	      assert(!SCIPsetIsInfinity(set, REALABS(solval)));
1561 	      return -solval; /* constants are ignored for computing the ray direction */
1562 	
1563 	   default:
1564 	      SCIPerrorMessage("unknown variable status\n");
1565 	      SCIPABORT();
1566 	      return 0.0; /*lint !e527*/
1567 	   }
1568 	}
1569 	
1570 	/** gets objective value of primal CIP solution in transformed problem */
1571 	SCIP_Real SCIPsolGetObj(
1572 	   SCIP_SOL*             sol,                /**< primal CIP solution */
1573 	   SCIP_SET*             set,                /**< global SCIP settings */
1574 	   SCIP_PROB*            transprob,          /**< tranformed problem data */
1575 	   SCIP_PROB*            origprob            /**< original problem data */
1576 	   )
1577 	{
1578 	   assert(sol != NULL);
1579 	
1580 	   /* for original solutions, sol->obj contains the external objective value */
1581 	   if( SCIPsolIsOriginal(sol) )
1582 	      return SCIPprobInternObjval(transprob, origprob, set, sol->obj);
1583 	   else
1584 	      return sol->obj;
1585 	}
1586 	
1587 	/** updates primal solutions after a change in a variable's objective value */
1588 	void SCIPsolUpdateVarObj(
1589 	   SCIP_SOL*             sol,                /**< primal CIP solution */
1590 	   SCIP_VAR*             var,                /**< problem variable */
1591 	   SCIP_Real             oldobj,             /**< old objective value */
1592 	   SCIP_Real             newobj              /**< new objective value */
1593 	   )
1594 	{
1595 	   SCIP_Real solval;
1596 	
1597 	   assert(sol != NULL);
1598 	   assert(!SCIPsolIsOriginal(sol));
1599 	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
1600 	
1601 	   solval = solGetArrayVal(sol, var);
1602 	   if( solval != SCIP_UNKNOWN ) /*lint !e777*/
1603 	      sol->obj += (newobj - oldobj) * solval;
1604 	}
1605 	
1606 	/* mark the given solution as partial solution */
1607 	SCIP_RETCODE SCIPsolMarkPartial(
1608 	   SCIP_SOL*             sol,                /**< primal CIP solution */
1609 	   SCIP_SET*             set,                /**< global SCIP settings */
1610 	   SCIP_STAT*            stat,               /**< problem statistics */
1611 	   SCIP_VAR**            vars,               /**< problem variables */
1612 	   int                   nvars               /**< number of problem variables */
1613 	   )
1614 	{
1615 	   SCIP_Real* vals;
1616 	   int v;
1617 	
1618 	   assert(sol != NULL);
1619 	   assert(sol->solorigin == SCIP_SOLORIGIN_ORIGINAL);
1620 	   assert(nvars == 0 || vars != NULL);
1621 	
1622 	   if( nvars == 0 )
1623 	      return SCIP_OKAY;;
1624 	
1625 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, nvars) );
1626 	
1627 	   /* get values */
1628 	   for( v = 0; v < nvars; v++ )
1629 	   {
1630 	      assert(!SCIPvarIsTransformed(vars[v]));
1631 	      vals[v] = SCIPsolGetVal(sol, set, stat, vars[v]);
1632 	   }
1633 	
1634 	   /* change origin to partial */
1635 	   sol->solorigin = SCIP_SOLORIGIN_PARTIAL;
1636 	
1637 	   /* set values */
1638 	   for( v = 0; v < nvars; v++ )
1639 	   {
1640 	      int idx = SCIPvarGetIndex(vars[v]);
1641 	
1642 	      if( vals[v] != SCIP_UNKNOWN ) /*lint !e777*/
1643 	      {
1644 	         /* from now on, variable must not be deleted */
1645 	         SCIPvarMarkNotDeletable(vars[v]);
1646 	
1647 	         /* mark the variable valid */
1648 	         SCIP_CALL( SCIPboolarraySetVal(sol->valid, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, TRUE) );
1649 	
1650 	         /* set the value in the solution array */
1651 	         SCIP_CALL( SCIPrealarraySetVal(sol->vals, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, vals[v]) );
1652 	      }
1653 	      else
1654 	      {
1655 	         /* mark the variable invalid */
1656 	         SCIP_CALL( SCIPboolarraySetVal(sol->valid, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, FALSE) );
1657 	      }
1658 	   }
1659 	
1660 	   /* free buffer */
1661 	   SCIPsetFreeBufferArray(set, &vals);
1662 	
1663 	   return SCIP_OKAY;
1664 	}
1665 	
1666 	/** checks solution for feasibility in original problem without adding it to the solution store
1667 	 *
1668 	 *  We first check the variable bounds. Then we loop over all constraint handlers and constraints, checking each in the
1669 	 *  order of their check priority.
1670 	 */
1671 	SCIP_RETCODE SCIPsolCheckOrig(
1672 	   SCIP_SOL*             sol,                /**< primal CIP solution */
1673 	   SCIP_SET*             set,                /**< global SCIP settings */
1674 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
1675 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1676 	   SCIP_STAT*            stat,               /**< problem statistics */
1677 	   SCIP_PROB*            prob,               /**< transformed problem data */
1678 	   SCIP_PRIMAL*          primal,             /**< primal data */
1679 	   SCIP_Bool             printreason,        /**< Should the reason for the violation be printed? */
1680 	   SCIP_Bool             completely,         /**< Should all violations be checked if printreason is true? */
1681 	   SCIP_Bool             checkbounds,        /**< Should the bounds of the variables be checked? */
1682 	   SCIP_Bool             checkintegrality,   /**< Has integrality to be checked? */
1683 	   SCIP_Bool             checklprows,        /**< Do constraints represented by rows in the current LP have to be checked? */
1684 	   SCIP_Bool             checkmodifiable,    /**< have modifiable constraint to be checked? */
1685 	   SCIP_Bool*            feasible            /**< stores whether given solution is feasible */
1686 	   )
1687 	{
1688 	   SCIP_RESULT result;
1689 	#ifndef NDEBUG
1690 	   int oldpriority;
1691 	#endif
1692 	   int v;
1693 	   int c;
1694 	   int h;
1695 	
1696 	   assert(sol != NULL);
1697 	   assert(set != NULL);
1698 	   assert(prob != NULL);
1699 	   assert(!prob->transformed);
1700 	   assert(feasible != NULL);
1701 	
1702 	   *feasible = TRUE;
1703 	
1704 	   SCIPsolResetViolations(sol);
1705 	
1706 	   if( !printreason )
1707 	      completely = FALSE;
1708 	
1709 	   /* check bounds */
1710 	   if( checkbounds )
1711 	   {
1712 	      for( v = 0; v < prob->nvars; ++v )
1713 	      {
1714 	         SCIP_VAR* var;
1715 	         SCIP_Real solval;
1716 	         SCIP_Real lb;
1717 	         SCIP_Real ub;
1718 	
1719 	         var = prob->vars[v];
1720 	         solval = SCIPsolGetVal(sol, set, stat, var);
1721 	
1722 	         lb = SCIPvarGetLbOriginal(var);
1723 	         ub = SCIPvarGetUbOriginal(var);
1724 	
1725 	         if( SCIPprimalUpdateViolations(primal) )
1726 	         {
1727 	            SCIPsolUpdateBoundViolation(sol, lb - solval, SCIPrelDiff(lb, solval));
1728 	            SCIPsolUpdateBoundViolation(sol, solval - ub, SCIPrelDiff(solval, ub));
1729 	         }
1730 	
1731 	         if( SCIPsetIsFeasLT(set, solval, lb) || SCIPsetIsFeasGT(set, solval, ub) )
1732 	         {
1733 	            *feasible = FALSE;
1734 	
1735 	            if( printreason )
1736 	            {
1737 	               SCIPmessagePrintInfo(messagehdlr, "solution violates original bounds of variable <%s> [%g,%g] solution value <%g>\n",
1738 	                  SCIPvarGetName(var), lb, ub, solval);
1739 	            }
1740 	
1741 	            if( !completely )
1742 	               return SCIP_OKAY;
1743 	         }
1744 	      }
1745 	   }
1746 	
1747 	   /* sort original constraint according to check priority */
1748 	   SCIP_CALL( SCIPprobSortConssCheck(prob) );
1749 	
1750 	   /* check original constraints
1751 	    *
1752 	    * in general modifiable constraints can not be checked, because the variables to fulfill them might be missing in
1753 	    * the original problem; however, if the solution comes from a heuristic during presolving, modifiable constraints
1754 	    * have to be checked;
1755 	    */
1756 	#ifndef NDEBUG
1757 	   oldpriority = INT_MAX;
1758 	#endif
1759 	   h = 0;
1760 	   for( c = 0; c < prob->nconss; ++c )
1761 	   {
1762 	      SCIP_CONS* cons;
1763 	      int priority;
1764 	
1765 	      cons = prob->origcheckconss[c];
1766 	      assert( SCIPconsGetHdlr(cons) != NULL );
1767 	      priority = SCIPconshdlrGetCheckPriority(SCIPconsGetHdlr(cons));
1768 	
1769 	#ifndef NDEBUG
1770 	      assert( priority <= oldpriority );
1771 	      oldpriority = priority;
1772 	#endif
1773 	
1774 	      /* check constraints handlers without constraints that have a check priority at least as high as current
1775 	       * constraint */
1776 	      while( h < set->nconshdlrs && SCIPconshdlrGetCheckPriority(set->conshdlrs[h]) >= priority )
1777 	      {
1778 	         if( !SCIPconshdlrNeedsCons(set->conshdlrs[h]) )
1779 	         {
1780 	            SCIP_CALL( SCIPconshdlrCheck(set->conshdlrs[h], blkmem, set, stat, sol,
1781 	                  checkintegrality, checklprows, printreason, completely, &result) );
1782 	
1783 	            if( result != SCIP_FEASIBLE )
1784 	            {
1785 	               *feasible = FALSE;
1786 	
1787 	               if( !completely )
1788 	                  return SCIP_OKAY;
1789 	            }
1790 	         }
1791 	         ++h;
1792 	      }
1793 	
1794 	      /* now check constraint */
1795 	      if( SCIPconsIsChecked(cons) && (checkmodifiable || !SCIPconsIsModifiable(cons)) )
1796 	      {
1797 	         /* check solution */
1798 	         SCIP_CALL( SCIPconsCheck(cons, set, sol, checkintegrality, checklprows, printreason, &result) );
1799 	
1800 	         if( result != SCIP_FEASIBLE )
1801 	         {
1802 	            *feasible = FALSE;
1803 	
1804 	            if( !completely )
1805 	               return SCIP_OKAY;
1806 	         }
1807 	      }
1808 	   }
1809 	
1810 	   /* one final loop over the remaining constraints handlers without constraints */
1811 	   while( h < set->nconshdlrs )
1812 	   {
1813 	      if( !SCIPconshdlrNeedsCons(set->conshdlrs[h]) )
1814 	      {
1815 	         SCIP_CALL( SCIPconshdlrCheck(set->conshdlrs[h], blkmem, set, stat, sol,
1816 	               checkintegrality, checklprows, printreason, completely, &result) );
1817 	
1818 	         if( result != SCIP_FEASIBLE )
1819 	         {
1820 	            *feasible = FALSE;
1821 	
1822 	            if( !completely )
1823 	               return SCIP_OKAY;
1824 	         }
1825 	      }
1826 	      ++h;
1827 	   }
1828 	
1829 	   return SCIP_OKAY;
1830 	}
1831 	
1832 	/** checks primal CIP solution for feasibility
1833 	 *
1834 	 *  @note The difference between SCIPsolCheck() and SCIPcheckSolOrig() is that modifiable constraints are handled
1835 	 *        differently. There might be some variables which do not have an original counter part (e.g. in
1836 	 *        branch-and-price). Therefore, modifiable constraints can not be double-checked in the original space.
1837 	 */
1838 	SCIP_RETCODE SCIPsolCheck(
1839 	   SCIP_SOL*             sol,                /**< primal CIP solution */
1840 	   SCIP_SET*             set,                /**< global SCIP settings */
1841 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
1842 	   BMS_BLKMEM*           blkmem,             /**< block memory */
1843 	   SCIP_STAT*            stat,               /**< problem statistics */
1844 	   SCIP_PROB*            prob,               /**< transformed problem data */
1845 	   SCIP_Bool             printreason,        /**< Should all reasons of violations be printed? */
1846 	   SCIP_Bool             completely,         /**< Should all violations be checked? */
1847 	   SCIP_Bool             checkbounds,        /**< Should the bounds of the variables be checked? */
1848 	   SCIP_Bool             checkintegrality,   /**< Has integrality to be checked? */
1849 	   SCIP_Bool             checklprows,        /**< Do constraints represented by rows in the current LP have to be checked? */
1850 	   SCIP_Bool*            feasible            /**< stores whether solution is feasible */
1851 	   )
1852 	{
1853 	   SCIP_RESULT result;
1854 	   int h;
1855 	
1856 	   assert(sol != NULL);
1857 	   assert(!SCIPsolIsOriginal(sol));
1858 	   assert(set != NULL);
1859 	   assert(prob != NULL);
1860 	   assert(feasible != NULL);
1861 	
1862 	   SCIPsetDebugMsg(set, "checking solution with objective value %g (nodenum=%" SCIP_LONGINT_FORMAT ", origin=%d)\n",
1863 	      sol->obj, sol->nodenum, sol->solorigin);
1864 	
1865 	   *feasible = TRUE;
1866 	
1867 	   SCIPsolResetViolations(sol);
1868 	
1869 	   if( !printreason )
1870 	      completely = FALSE;
1871 	
1872 	   /* check whether the solution respects the global bounds of the variables */
1873 	   if( checkbounds || sol->hasinfval )
1874 	   {
1875 	      int v;
1876 	
1877 	      for( v = 0; v < prob->nvars && (*feasible || completely); ++v )
1878 	      {
1879 	         SCIP_VAR* var;
1880 	         SCIP_Real solval;
1881 	
1882 	         var = prob->vars[v];
1883 	         solval = SCIPsolGetVal(sol, set, stat, var);
1884 	
1885 	         if( solval != SCIP_UNKNOWN ) /*lint !e777*/
1886 	         {
1887 	            SCIP_Real lb;
1888 	            SCIP_Real ub;
1889 	
1890 	            lb = SCIPvarGetLbGlobal(var);
1891 	            ub = SCIPvarGetUbGlobal(var);
1892 	
1893 	            /* if we have to check bound and one of the current bounds is violated */
1894 	            if( checkbounds && ((!SCIPsetIsInfinity(set, -lb) && SCIPsetIsFeasLT(set, solval, lb))
1895 	                     || (!SCIPsetIsInfinity(set, ub) && SCIPsetIsFeasGT(set, solval, ub))) )
1896 	            {
1897 	               *feasible = FALSE;
1898 	
1899 	               if( printreason )
1900 	               {
1901 	                  SCIPmessagePrintInfo(messagehdlr, "solution value %g violates bounds of <%s>[%g,%g] by %g\n", solval, SCIPvarGetName(var),
1902 	                        SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), MAX(lb - solval, 0.0) + MAX(solval - ub, 0.0));
1903 	               }
1904 	#ifdef SCIP_DEBUG
1905 	               else
1906 	               {
1907 	                  SCIPsetDebugMsgPrint(set, "  -> solution value %g violates bounds of <%s>[%g,%g]\n", solval, SCIPvarGetName(var),
1908 	                        SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var));
1909 	               }
1910 	#endif
1911 	            }
1912 	
1913 	            /* check whether there are infinite variable values that lead to an objective value of +infinity */
1914 	            if( *feasible && sol->hasinfval )
1915 	            {
1916 	               *feasible = *feasible && (!SCIPsetIsInfinity(set, solval) || SCIPsetIsLE(set, SCIPvarGetUnchangedObj(var), 0.0) );
1917 	               *feasible = *feasible && (!SCIPsetIsInfinity(set, -solval) || SCIPsetIsGE(set, SCIPvarGetUnchangedObj(var), 0.0) );
1918 	
1919 	               if( ((SCIPsetIsInfinity(set, solval) && SCIPsetIsGT(set, SCIPvarGetUnchangedObj(var), 0.0)) || (SCIPsetIsInfinity(set, -solval) && SCIPsetIsLT(set, SCIPvarGetUnchangedObj(var), 0.0))) )
1920 	               {
1921 	                  if( printreason )
1922 	                  {
1923 	                     SCIPmessagePrintInfo(messagehdlr, "infinite solution value %g for variable  <%s> with obj %g implies objective value +infinity\n",
1924 	                        solval, SCIPvarGetName(var), SCIPvarGetUnchangedObj(var));
1925 	                  }
1926 	#ifdef SCIP_DEBUG
1927 	                  else
1928 	                  {
1929 	                     SCIPsetDebugMsgPrint(set, "infinite solution value %g for variable  <%s> with obj %g implies objective value +infinity\n",
1930 	                        solval, SCIPvarGetName(var), SCIPvarGetUnchangedObj(var));
1931 	                  }
1932 	#endif
1933 	               }
1934 	            }
1935 	         }
1936 	      }
1937 	   }
1938 	
1939 	   /* check whether the solution fulfills all constraints */
1940 	   for( h = 0; h < set->nconshdlrs && (*feasible || completely); ++h )
1941 	   {
1942 	      SCIP_CALL( SCIPconshdlrCheck(set->conshdlrs[h], blkmem, set, stat, sol,
1943 	            checkintegrality, checklprows, printreason, completely, &result) );
1944 	      *feasible = *feasible && (result == SCIP_FEASIBLE);
1945 	
1946 	#ifdef SCIP_DEBUG
1947 	      if( !(*feasible) )
1948 	      {
1949 	         SCIPdebugPrintf("  -> infeasibility detected in constraint handler <%s>\n",
1950 	            SCIPconshdlrGetName(set->conshdlrs[h]));
1951 	      }
1952 	#endif
1953 	   }
1954 	
1955 	   return SCIP_OKAY;
1956 	}
1957 	
1958 	/** try to round given solution */
1959 	SCIP_RETCODE SCIPsolRound(
1960 	   SCIP_SOL*             sol,                /**< primal solution */
1961 	   SCIP_SET*             set,                /**< global SCIP settings */
1962 	   SCIP_STAT*            stat,               /**< problem statistics data */
1963 	   SCIP_PROB*            prob,               /**< transformed problem data */
1964 	   SCIP_TREE*            tree,               /**< branch and bound tree */
1965 	   SCIP_Bool*            success             /**< pointer to store whether rounding was successful */
1966 	   )
1967 	{
1968 	   int nvars;
1969 	   int v;
1970 	
1971 	   assert(sol != NULL);
1972 	   assert(!SCIPsolIsOriginal(sol));
1973 	   assert(prob != NULL);
1974 	   assert(prob->transformed);
1975 	   assert(success != NULL);
1976 	
1977 	   /* round all roundable fractional variables in the corresponding direction as long as no unroundable var was found */
1978 	   nvars = prob->nbinvars + prob->nintvars;
1979 	   for( v = 0; v < nvars; ++v )
1980 	   {
1981 	      SCIP_VAR* var;
1982 	      SCIP_Real solval;
1983 	      SCIP_Bool mayrounddown;
1984 	      SCIP_Bool mayroundup;
1985 	
1986 	      var = prob->vars[v];
1987 	      assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
1988 	      assert(sol->solorigin != SCIP_SOLORIGIN_LPSOL || SCIPboolarrayGetVal(sol->valid, SCIPvarGetIndex(var))
1989 	         || sol->lpcount == stat->lpcount);
1990 	      solval = solGetArrayVal(sol, var);
1991 	
1992 	      /* solutions with unknown entries cannot be rounded */
1993 	      if( solval == SCIP_UNKNOWN ) /*lint !e777*/
1994 	         break;
1995 	
1996 	      /* if solution value is already integral with feastol, continue */
1997 	      if( SCIPsetIsFeasIntegral(set, solval) )
1998 	         continue;
1999 	
2000 	      /* get rounding possibilities */
2001 	      mayrounddown = SCIPvarMayRoundDown(var);
2002 	      mayroundup = SCIPvarMayRoundUp(var);
2003 	
2004 	      /* choose rounding direction */
2005 	      if( mayrounddown && mayroundup )
2006 	      {
2007 	         /* we can round in both directions: round in objective function direction */
2008 	         if( SCIPvarGetUnchangedObj(var) >= 0.0 )
2009 	            solval = SCIPsetFeasFloor(set, solval);
2010 	         else
2011 	            solval = SCIPsetFeasCeil(set, solval);
2012 	      }
2013 	      else if( mayrounddown )
2014 	         solval = SCIPsetFeasFloor(set, solval);
2015 	      else if( mayroundup )
2016 	         solval = SCIPsetFeasCeil(set, solval);
2017 	      else
2018 	         break;
2019 	
2020 	      /* store new solution value */
2021 	      SCIP_CALL( SCIPsolSetVal(sol, set, stat, tree, var, solval) );
2022 	   }
2023 	
2024 	   /* check, if rounding was successful */
2025 	   *success = (v == nvars);
2026 	
2027 	   return SCIP_OKAY;
2028 	}
2029 	
2030 	/** updates the solution value sums in variables by adding the value in the given solution */
2031 	void SCIPsolUpdateVarsum(
2032 	   SCIP_SOL*             sol,                /**< primal CIP solution */
2033 	   SCIP_SET*             set,                /**< global SCIP settings */
2034 	   SCIP_STAT*            stat,               /**< problem statistics data */
2035 	   SCIP_PROB*            prob,               /**< transformed problem data */
2036 	   SCIP_Real             weight              /**< weight of solution in weighted average */
2037 	   )
2038 	{
2039 	   SCIP_Real solval;
2040 	   int v;
2041 	
2042 	   assert(sol != NULL);
2043 	   assert(!SCIPsolIsOriginal(sol));
2044 	   assert(0.0 <= weight && weight <= 1.0);
2045 	
2046 	   for( v = 0; v < prob->nvars; ++v )
2047 	   {
2048 	      assert(prob->vars[v] != NULL);
2049 	      solval = SCIPsolGetVal(sol, set, stat, prob->vars[v]);
2050 	      if( solval != SCIP_UNKNOWN ) /*lint !e777*/
2051 	      {
2052 	         prob->vars[v]->primsolavg *= (1.0-weight);
2053 	         prob->vars[v]->primsolavg += weight*solval;
2054 	      }
2055 	   }
2056 	}
2057 	
2058 	/** retransforms solution to original problem space */
2059 	SCIP_RETCODE SCIPsolRetransform(
2060 	   SCIP_SOL*             sol,                /**< primal CIP solution */
2061 	   SCIP_SET*             set,                /**< global SCIP settings */
2062 	   SCIP_STAT*            stat,               /**< problem statistics data */
2063 	   SCIP_PROB*            origprob,           /**< original problem */
2064 	   SCIP_PROB*            transprob,          /**< transformed problem */
2065 	   SCIP_Bool*            hasinfval           /**< pointer to store whether the solution has infinite values */
2066 	   )
2067 	{
2068 	   SCIP_VAR** transvars;
2069 	   SCIP_VAR** vars;
2070 	   SCIP_VAR** activevars;
2071 	   SCIP_Real* solvals;
2072 	   SCIP_Real* activevals;
2073 	   SCIP_Real* transsolvals;
2074 	   SCIP_Real constant;
2075 	   int requiredsize;
2076 	   int ntransvars;
2077 	   int nactivevars;
2078 	   int nvars;
2079 	   int v;
2080 	   int i;
2081 	
2082 	   assert(sol != NULL);
2083 	   assert(sol->solorigin == SCIP_SOLORIGIN_ZERO);
2084 	   assert(origprob != NULL);
2085 	   assert(transprob != NULL);
2086 	   assert(hasinfval != NULL);
2087 	   assert(!origprob->transformed);
2088 	   assert(transprob->transformed);
2089 	
2090 	   *hasinfval = FALSE;
2091 	
2092 	   /* This method was a performance bottleneck when retransforming a solution during presolving, before flattening the
2093 	    * aggregation graph. In that case, calling SCIPsolGetVal() on the original variable consumed too much
2094 	    * time. Therefore, we now first compute the active representation of each original variable using
2095 	    * SCIPvarGetActiveRepresentatives(), which is much faster, and sum up the solution values of the active variables by
2096 	    * hand for each original variable.
2097 	    */
2098 	   vars = origprob->vars;
2099 	   nvars = origprob->nvars;
2100 	   transvars = transprob->vars;
2101 	   ntransvars = transprob->nvars;
2102 	
2103 	   /* allocate temporary memory for getting the active representation of the original variables, buffering the solution
2104 	    * values of all active variables and storing the original solution values
2105 	    */
2106 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &transsolvals, ntransvars + 1) );
2107 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, ntransvars + 1) );
2108 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &activevals, ntransvars + 1) );
2109 	   SCIP_CALL( SCIPsetAllocBufferArray(set, &solvals, nvars) );
2110 	   assert(transsolvals != NULL); /* for flexelint */
2111 	   assert(solvals != NULL); /* for flexelint */
2112 	
2113 	   /* get the solution values of all active variables */
2114 	   for( v = 0; v < ntransvars; ++v )
2115 	   {
2116 	      transsolvals[v] = SCIPsolGetVal(sol, set, stat, transvars[v]);
2117 	   }
2118 	
2119 	   /* get the solution in original problem variables */
2120 	   for( v = 0; v < nvars; ++v )
2121 	   {
2122 	      activevars[0] = vars[v];
2123 	      activevals[0] = 1.0;
2124 	      nactivevars = 1;
2125 	      constant = 0.0;
2126 	
2127 	      /* get active representation of the original variable */
2128 	      SCIP_CALL( SCIPvarGetActiveRepresentatives(set, activevars, activevals, &nactivevars, ntransvars + 1, &constant,
2129 	            &requiredsize, TRUE) );
2130 	      assert(requiredsize <= ntransvars);
2131 	
2132 	      /* compute solution value of the original variable */
2133 	      solvals[v] = constant;
2134 	      for( i = 0; i < nactivevars; ++i )
2135 	      {
2136 	         assert(0 <= SCIPvarGetProbindex(activevars[i]) && SCIPvarGetProbindex(activevars[i]) < ntransvars);
2137 	         assert(!SCIPsetIsInfinity(set, -solvals[v]) || !SCIPsetIsInfinity(set, activevals[i] * transsolvals[SCIPvarGetProbindex(activevars[i])]));
2138 	         assert(!SCIPsetIsInfinity(set, solvals[v]) || !SCIPsetIsInfinity(set, -activevals[i] * transsolvals[SCIPvarGetProbindex(activevars[i])]));
2139 	         solvals[v] += activevals[i] * transsolvals[SCIPvarGetProbindex(activevars[i])];
2140 	      }
2141 	
2142 	      if( SCIPsetIsInfinity(set, solvals[v]) )
2143 	      {
2144 	         solvals[v] = SCIPsetInfinity(set);
2145 	         *hasinfval = TRUE;
2146 	      }
2147 	      else if( SCIPsetIsInfinity(set, -solvals[v]) )
2148 	      {
2149 	         solvals[v] = -SCIPsetInfinity(set);
2150 	         *hasinfval = TRUE;
2151 	      }
2152 	   }
2153 	
2154 	   /* clear the solution and convert it into original space */
2155 	   SCIP_CALL( solClearArrays(sol) );
2156 	   sol->solorigin = SCIP_SOLORIGIN_ORIGINAL;
2157 	   sol->obj = origprob->objoffset;
2158 	
2159 	   /* reinsert the values of the original variables */
2160 	   for( v = 0; v < nvars; ++v )
2161 	   {
2162 	      assert(SCIPvarGetUnchangedObj(vars[v]) == SCIPvarGetObj(vars[v])); /*lint !e777*/
2163 	
2164 	      if( solvals[v] != 0.0 )
2165 	      {
2166 	         SCIP_CALL( solSetArrayVal(sol, set, vars[v], solvals[v]) );
2167 	         if( solvals[v] != SCIP_UNKNOWN ) /*lint !e777*/
2168 	            sol->obj += SCIPvarGetUnchangedObj(vars[v]) * solvals[v];
2169 	      }
2170 	   }
2171 	
2172 	   /**@todo remember the variables without original counterpart (priced variables) in the solution */
2173 	
2174 	   /* free temporary memory */
2175 	   SCIPsetFreeBufferArray(set, &solvals);
2176 	   SCIPsetFreeBufferArray(set, &activevals);
2177 	   SCIPsetFreeBufferArray(set, &activevars);
2178 	   SCIPsetFreeBufferArray(set, &transsolvals);
2179 	
2180 	   return SCIP_OKAY;
2181 	}
2182 	
2183 	/** recomputes the objective value of an original solution, e.g., when transferring solutions
2184 	 *  from the solution pool (objective coefficients might have changed in the meantime)
2185 	 */
2186 	void SCIPsolRecomputeObj(
2187 	   SCIP_SOL*             sol,                /**< primal CIP solution */
2188 	   SCIP_SET*             set,                /**< global SCIP settings */
2189 	   SCIP_STAT*            stat,               /**< problem statistics data */
2190 	   SCIP_PROB*            origprob            /**< original problem */
2191 	   )
2192 	{
2193 	   SCIP_VAR** vars;
2194 	   SCIP_Real solval;
2195 	   int nvars;
2196 	   int v;
2197 	
2198 	   assert(sol != NULL);
2199 	   assert(SCIPsolIsOriginal(sol));
2200 	   assert(origprob != NULL);
2201 	
2202 	   vars = origprob->vars;
2203 	   nvars = origprob->nvars;
2204 	
2205 	   /* recompute the objective value */
2206 	   sol->obj = SCIPprobGetObjoffset(origprob);
2207 	   for( v = 0; v < nvars; ++v )
2208 	   {
2209 	      solval = SCIPsolGetVal(sol, set, stat, vars[v]);
2210 	      if( solval != 0.0 && solval != SCIP_UNKNOWN ) /*lint !e777*/
2211 	      {
2212 	         sol->obj += SCIPvarGetUnchangedObj(vars[v]) * solval;
2213 	      }
2214 	   }
2215 	
2216 	   if( SCIPsetIsInfinity(set, -sol->obj) )
2217 	      sol->obj = -SCIPsetInfinity(set);
2218 	}
2219 	
2220 	/** returns whether the given solutions are equal */
2221 	SCIP_Bool SCIPsolsAreEqual(
2222 	   SCIP_SOL*             sol1,               /**< first primal CIP solution */
2223 	   SCIP_SOL*             sol2,               /**< second primal CIP solution */
2224 	   SCIP_SET*             set,                /**< global SCIP settings */
2225 	   SCIP_STAT*            stat,               /**< problem statistics data */
2226 	   SCIP_PROB*            origprob,           /**< original problem */
2227 	   SCIP_PROB*            transprob           /**< transformed problem after presolve, or NULL if both solution are
2228 	                                              *   defined in the original problem space */
2229 	   )
2230 	{
2231 	   SCIP_PROB* prob;
2232 	   SCIP_Bool infobjs;
2233 	   SCIP_Real obj1;
2234 	   SCIP_Real obj2;
2235 	   int v;
2236 	
2237 	   assert(sol1 != NULL);
2238 	   assert(sol2 != NULL);
2239 	   assert((SCIPsolIsOriginal(sol1) && SCIPsolIsOriginal(sol2)) || transprob != NULL);
2240 	
2241 	   /* if both solutions are original or both are transformed, take the objective values stored in the solutions */
2242 	   if( SCIPsolIsOriginal(sol1) == SCIPsolIsOriginal(sol2) )
2243 	   {
2244 	      obj1 = sol1->obj;
2245 	      obj2 = sol2->obj;
2246 	   }
2247 	   /* one solution is original and the other not, so we have to get for both the objective in the transformed problem */
2248 	   else
2249 	   {
2250 	      obj1 = SCIPsolGetObj(sol1, set, transprob, origprob);
2251 	      obj2 = SCIPsolGetObj(sol2, set, transprob, origprob);
2252 	   }
2253 	
2254 	   /* solutions with different objective values cannot be the same; we consider two infinite objective values with the
2255 	    * same sign always to be different
2256 	    */
2257 	   infobjs = (SCIPsetIsInfinity(set, obj1) && SCIPsetIsInfinity(set, obj2))
2258 	      || (SCIPsetIsInfinity(set, -obj1) && SCIPsetIsInfinity(set, -obj2));
2259 	   if( !infobjs && !SCIPsetIsEQ(set, obj1, obj2) )
2260 	      return FALSE;
2261 	
2262 	   /* if one of the solutions is defined in the original space, the comparison has to be performed in the original
2263 	    * space
2264 	    */
2265 	   prob = transprob;
2266 	   if( SCIPsolIsOriginal(sol1) || SCIPsolIsOriginal(sol2) )
2267 	      prob = origprob;
2268 	   assert(prob != NULL);
2269 	
2270 	   /* compare each variable value */
2271 	   for( v = 0; v < prob->nvars; ++v )
2272 	   {
2273 	      SCIP_Real val1;
2274 	      SCIP_Real val2;
2275 	
2276 	      val1 = SCIPsolGetVal(sol1, set, stat, prob->vars[v]);
2277 	      val2 = SCIPsolGetVal(sol2, set, stat, prob->vars[v]);
2278 	      if( !SCIPsetIsEQ(set, val1, val2) )
2279 	         return FALSE;
2280 	   }
2281 	
2282 	   return TRUE;
2283 	}
2284 	
2285 	/** outputs non-zero elements of solution to file stream */
2286 	SCIP_RETCODE SCIPsolPrint(
2287 	   SCIP_SOL*             sol,                /**< primal CIP solution */
2288 	   SCIP_SET*             set,                /**< global SCIP settings */
2289 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2290 	   SCIP_STAT*            stat,               /**< problem statistics data */
2291 	   SCIP_PROB*            prob,               /**< problem data (original or transformed) */
2292 	   SCIP_PROB*            transprob,          /**< transformed problem data or NULL (to display priced variables) */
2293 	   FILE*                 file,               /**< output file (or NULL for standard output) */
2294 	   SCIP_Bool             mipstart,           /**< should only discrete variables be printed? */
2295 	   SCIP_Bool             printzeros          /**< should variables set to zero be printed? */
2296 	   )
2297 	{
2298 	   SCIP_Real solval;
2299 	   int v;
2300 	
2301 	   assert(sol != NULL);
2302 	   assert(prob != NULL);
2303 	   assert(SCIPsolIsOriginal(sol) || prob->transformed || transprob != NULL);
2304 	   assert(!mipstart || !SCIPsolIsPartial(sol));
2305 	
2306 	   /* display variables of problem data */
2307 	   for( v = 0; v < prob->nfixedvars; ++v )
2308 	   {
2309 	      assert(prob->fixedvars[v] != NULL);
2310 	
2311 	      /* skip non-discrete variables in a mip start */
2312 	      if( mipstart && !SCIPvarIsIntegral(prob->fixedvars[v]) )
2313 	         continue;
2314 	
2315 	      solval = SCIPsolGetVal(sol, set, stat, prob->fixedvars[v]);
2316 	      if( printzeros || mipstart
2317 	         || (sol->solorigin != SCIP_SOLORIGIN_PARTIAL && !SCIPsetIsZero(set, solval))
2318 	         || (sol->solorigin == SCIP_SOLORIGIN_PARTIAL && solval != SCIP_UNKNOWN) ) /*lint !e777*/
2319 	      {
2320 	         SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(prob->fixedvars[v]));
2321 	         if( solval == SCIP_UNKNOWN ) /*lint !e777*/
2322 	            SCIPmessageFPrintInfo(messagehdlr, file, "              unknown");
2323 	         else if( SCIPsetIsInfinity(set, solval) )
2324 	            SCIPmessageFPrintInfo(messagehdlr, file, "            +infinity");
2325 	         else if( SCIPsetIsInfinity(set, -solval) )
2326 	            SCIPmessageFPrintInfo(messagehdlr, file, "            -infinity");
2327 	         else
2328 	            SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval);
2329 	         SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetUnchangedObj(prob->fixedvars[v]));
2330 	      }
2331 	   }
2332 	
2333 	   for( v = 0; v < prob->nvars; ++v )
2334 	   {
2335 	      assert(prob->vars[v] != NULL);
2336 	
2337 	      /* skip non-discrete variables in a mip start */
2338 	      if( mipstart && !SCIPvarIsIntegral(prob->vars[v]) )
2339 	         continue;
2340 	
2341 	      solval = SCIPsolGetVal(sol, set, stat, prob->vars[v]);
2342 	      if( printzeros || mipstart
2343 	         || (sol->solorigin != SCIP_SOLORIGIN_PARTIAL && !SCIPsetIsZero(set, solval))
2344 	         || (sol->solorigin == SCIP_SOLORIGIN_PARTIAL && solval != SCIP_UNKNOWN) ) /*lint !e777*/
2345 	      {
2346 	         SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(prob->vars[v]));
2347 	         if( solval == SCIP_UNKNOWN ) /*lint !e777*/
2348 	            SCIPmessageFPrintInfo(messagehdlr, file, "              unknown");
2349 	         else if( SCIPsetIsInfinity(set, solval) )
2350 	            SCIPmessageFPrintInfo(messagehdlr, file, "            +infinity");
2351 	         else if( SCIPsetIsInfinity(set, -solval) )
2352 	            SCIPmessageFPrintInfo(messagehdlr, file, "            -infinity");
2353 	         else
2354 	            SCIPmessageFPrintInfo(messagehdlr, file, " %20.15g", solval);
2355 	         SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetUnchangedObj(prob->vars[v]));
2356 	      }
2357 	   }
2358 	
2359 	   /* display additional priced variables (if given problem data is original problem); consider these variables only
2360 	    * if there is at least one active pricer, otherwise we might print variables that have been added by, e.g., the
2361 	    * dual sparsify presolver (see #2946)
2362 	    */
2363 	   if( !prob->transformed && !SCIPsolIsOriginal(sol) && set->nactivepricers > 0 )
2364 	   {
2365 	      assert(transprob != NULL);
2366 	      for( v = 0; v < transprob->nfixedvars; ++v )
2367 	      {
2368 	         assert(transprob->fixedvars[v] != NULL);
2369 	         if( SCIPvarIsTransformedOrigvar(transprob->fixedvars[v]) )
2370 	            continue;
2371 	
2372 	         /* skip non-discrete variables in a mip start */
2373 	         if( mipstart && !SCIPvarIsIntegral(transprob->fixedvars[v]) )
2374 	            continue;
2375 	
2376 	         solval = SCIPsolGetVal(sol, set, stat, transprob->fixedvars[v]);
2377 	         if( printzeros || mipstart || !SCIPsetIsZero(set, solval) )
2378 	         {
2379 	            SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(transprob->fixedvars[v]));
2380 	            if( solval == SCIP_UNKNOWN ) /*lint !e777*/
2381 	               SCIPmessageFPrintInfo(messagehdlr, file, "              unknown");
2382 	            else if( SCIPsetIsInfinity(set, solval) )
2383 	               SCIPmessageFPrintInfo(messagehdlr, file, "            +infinity");
2384 	            else if( SCIPsetIsInfinity(set, -solval) )
2385 	               SCIPmessageFPrintInfo(messagehdlr, file, "            -infinity");
2386 	            else
2387 	               SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval);
2388 	            SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetUnchangedObj(transprob->fixedvars[v]));
2389 	         }
2390 	      }
2391 	      for( v = 0; v < transprob->nvars; ++v )
2392 	      {
2393 	         assert(transprob->vars[v] != NULL);
2394 	         if( SCIPvarIsTransformedOrigvar(transprob->vars[v]) )
2395 	            continue;
2396 	
2397 	         /* skip non-discrete variables in a mip start */
2398 	         if( mipstart && !SCIPvarIsIntegral(transprob->vars[v]) )
2399 	            continue;
2400 	
2401 	         solval = SCIPsolGetVal(sol, set, stat, transprob->vars[v]);
2402 	         if( printzeros || !SCIPsetIsZero(set, solval) )
2403 	         {
2404 	            SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(transprob->vars[v]));
2405 	            if( solval == SCIP_UNKNOWN ) /*lint !e777*/
2406 	               SCIPmessageFPrintInfo(messagehdlr, file, "              unknown");
2407 	            else if( SCIPsetIsInfinity(set, solval) )
2408 	               SCIPmessageFPrintInfo(messagehdlr, file, "            +infinity");
2409 	            else if( SCIPsetIsInfinity(set, -solval) )
2410 	               SCIPmessageFPrintInfo(messagehdlr, file, "            -infinity");
2411 	            else
2412 	               SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval);
2413 	            SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetUnchangedObj(transprob->vars[v]));
2414 	         }
2415 	      }
2416 	   }
2417 	
2418 	   return SCIP_OKAY;
2419 	}
2420 	
2421 	/** outputs non-zero elements of solution representing a ray to file stream */
2422 	SCIP_RETCODE SCIPsolPrintRay(
2423 	   SCIP_SOL*             sol,                /**< primal CIP solution */
2424 	   SCIP_SET*             set,                /**< global SCIP settings */
2425 	   SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2426 	   SCIP_STAT*            stat,               /**< problem statistics data */
2427 	   SCIP_PROB*            prob,               /**< problem data (original or transformed) */
2428 	   SCIP_PROB*            transprob,          /**< transformed problem data or NULL (to display priced variables) */
2429 	   FILE*                 file,               /**< output file (or NULL for standard output) */
2430 	   SCIP_Bool             printzeros          /**< should variables set to zero be printed? */
2431 	   )
2432 	{
2433 	   SCIP_Real solval;
2434 	   int v;
2435 	
2436 	   assert(sol != NULL);
2437 	   assert(prob != NULL);
2438 	   assert(SCIPsolIsOriginal(sol) || prob->transformed || transprob != NULL);
2439 	
2440 	   /* display variables of problem data */
2441 	   for( v = 0; v < prob->nfixedvars; ++v )
2442 	   {
2443 	      assert(prob->fixedvars[v] != NULL);
2444 	      solval = SCIPsolGetRayVal(sol, set, stat, prob->fixedvars[v]);
2445 	      if( printzeros || !SCIPsetIsZero(set, solval) )
2446 	      {
2447 	         SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(prob->fixedvars[v]));
2448 	         if( solval == SCIP_UNKNOWN ) /*lint !e777*/
2449 	            SCIPmessageFPrintInfo(messagehdlr, file, "              unknown");
2450 	         else if( SCIPsetIsInfinity(set, solval) )
2451 	            SCIPmessageFPrintInfo(messagehdlr, file, "            +infinity");
2452 	         else if( SCIPsetIsInfinity(set, -solval) )
2453 	            SCIPmessageFPrintInfo(messagehdlr, file, "            -infinity");
2454 	         else
2455 	            SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval);
2456 	         SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetUnchangedObj(prob->fixedvars[v]));
2457 	      }
2458 	   }
2459 	   for( v = 0; v < prob->nvars; ++v )
2460 	   {
2461 	      assert(prob->vars[v] != NULL);
2462 	      solval = SCIPsolGetRayVal(sol, set, stat, prob->vars[v]);
2463 	      if( printzeros || !SCIPsetIsZero(set, solval) )
2464 	      {
2465 	         SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(prob->vars[v]));
2466 	         if( solval == SCIP_UNKNOWN ) /*lint !e777*/
2467 	            SCIPmessageFPrintInfo(messagehdlr, file, "              unknown");
2468 	         else if( SCIPsetIsInfinity(set, solval) )
2469 	            SCIPmessageFPrintInfo(messagehdlr, file, "            +infinity");
2470 	         else if( SCIPsetIsInfinity(set, -solval) )
2471 	            SCIPmessageFPrintInfo(messagehdlr, file, "            -infinity");
2472 	         else
2473 	            SCIPmessageFPrintInfo(messagehdlr, file, " %20.15g", solval);
2474 	         SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetUnchangedObj(prob->vars[v]));
2475 	      }
2476 	   }
2477 	
2478 	   /* display additional priced variables (if given problem data is original problem) */
2479 	   if( !prob->transformed && !SCIPsolIsOriginal(sol) )
2480 	   {
2481 	      assert(transprob != NULL);
2482 	      for( v = 0; v < transprob->nfixedvars; ++v )
2483 	      {
2484 	         assert(transprob->fixedvars[v] != NULL);
2485 	         if( SCIPvarIsTransformedOrigvar(transprob->fixedvars[v]) )
2486 	            continue;
2487 	
2488 	         solval = SCIPsolGetRayVal(sol, set, stat, transprob->fixedvars[v]);
2489 	         if( printzeros || !SCIPsetIsZero(set, solval) )
2490 	         {
2491 	            SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(transprob->fixedvars[v]));
2492 	            if( solval == SCIP_UNKNOWN ) /*lint !e777*/
2493 	               SCIPmessageFPrintInfo(messagehdlr, file, "              unknown");
2494 	            else if( SCIPsetIsInfinity(set, solval) )
2495 	               SCIPmessageFPrintInfo(messagehdlr, file, "            +infinity");
2496 	            else if( SCIPsetIsInfinity(set, -solval) )
2497 	               SCIPmessageFPrintInfo(messagehdlr, file, "            -infinity");
2498 	            else
2499 	               SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval);
2500 	            SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetUnchangedObj(transprob->fixedvars[v]));
2501 	         }
2502 	      }
2503 	      for( v = 0; v < transprob->nvars; ++v )
2504 	      {
2505 	         assert(transprob->vars[v] != NULL);
2506 	         if( SCIPvarIsTransformedOrigvar(transprob->vars[v]) )
2507 	            continue;
2508 	
2509 	         solval = SCIPsolGetRayVal(sol, set, stat, transprob->vars[v]);
2510 	         if( printzeros || !SCIPsetIsZero(set, solval) )
2511 	         {
2512 	            SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(transprob->vars[v]));
2513 	            if( solval == SCIP_UNKNOWN ) /*lint !e777*/
2514 	               SCIPmessageFPrintInfo(messagehdlr, file, "              unknown");
2515 	            else if( SCIPsetIsInfinity(set, solval) )
2516 	               SCIPmessageFPrintInfo(messagehdlr, file, "            +infinity");
2517 	            else if( SCIPsetIsInfinity(set, -solval) )
2518 	               SCIPmessageFPrintInfo(messagehdlr, file, "            -infinity");
2519 	            else
2520 	               SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval);
2521 	            SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetUnchangedObj(transprob->vars[v]));
2522 	         }
2523 	      }
2524 	   }
2525 	
2526 	   return SCIP_OKAY;
2527 	}
2528 	
2529 	/*
2530 	 * methods for accumulated numerical violations of a solution
2531 	 */
2532 	
2533 	/** reset violations of a solution */
2534 	void SCIPsolResetViolations(
2535 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2536 	   )
2537 	{
2538 	   assert(sol != NULL);
2539 	
2540 	   sol->viol.absviolbounds = 0.0;
2541 	   sol->viol.relviolbounds = 0.0;
2542 	   sol->viol.absviolintegrality = 0.0;
2543 	   sol->viol.absviollprows = 0.0;
2544 	   sol->viol.relviollprows = 0.0;
2545 	   sol->viol.absviolcons = 0.0;
2546 	   sol->viol.relviolcons = 0.0;
2547 	}
2548 	
2549 	/** update integrality violation of a solution */
2550 	void SCIPsolUpdateIntegralityViolation(
2551 	   SCIP_SOL*             sol,                /**< primal CIP solution */
2552 	   SCIP_Real             absviolintegrality  /**< absolute violation of integrality */
2553 	   )
2554 	{
2555 	   assert(sol != NULL);
2556 	
2557 	   sol->viol.absviolintegrality = MAX(sol->viol.absviolintegrality, absviolintegrality);
2558 	}
2559 	
2560 	/** update bound violation of a solution */
2561 	void SCIPsolUpdateBoundViolation(
2562 	   SCIP_SOL*             sol,                /**< primal CIP solution */
2563 	   SCIP_Real             absviolbounds,      /**< absolute violation of bounds */
2564 	   SCIP_Real             relviolbounds       /**< relative violation of bounds */
2565 	   )
2566 	{
2567 	   assert(sol != NULL);
2568 	
2569 	   sol->viol.absviolbounds = MAX(sol->viol.absviolbounds, absviolbounds);
2570 	   sol->viol.relviolbounds = MAX(sol->viol.relviolbounds, relviolbounds);
2571 	}
2572 	
2573 	/** update LP row violation of a solution */
2574 	void SCIPsolUpdateLPRowViolation(
2575 	   SCIP_SOL*             sol,                /**< primal CIP solution */
2576 	   SCIP_Real             absviollprows,      /**< absolute violation of LP rows */
2577 	   SCIP_Real             relviollprows       /**< relative violation of LP rows */
2578 	   )
2579 	{
2580 	   assert(sol != NULL);
2581 	
2582 	   sol->viol.absviollprows = MAX(sol->viol.absviollprows, absviollprows);
2583 	   sol->viol.relviollprows = MAX(sol->viol.relviollprows, relviollprows);
2584 	}
2585 	
2586 	/** update constraint violation of a solution */
2587 	void SCIPsolUpdateConsViolation(
2588 	   SCIP_SOL*             sol,                /**< primal CIP solution */
2589 	   SCIP_Real             absviolcons,        /**< absolute violation of constraint */
2590 	   SCIP_Real             relviolcons         /**< relative violation of constraint */
2591 	   )
2592 	{
2593 	   assert(sol != NULL);
2594 	
2595 	   sol->viol.absviolcons = MAX(sol->viol.absviolcons, absviolcons);
2596 	   sol->viol.relviolcons = MAX(sol->viol.relviolcons, relviolcons);
2597 	}
2598 	
2599 	/** update violation of a constraint that is represented in the LP */
2600 	void SCIPsolUpdateLPConsViolation(
2601 	   SCIP_SOL*             sol,                /**< primal CIP solution */
2602 	   SCIP_Real             absviol,            /**< absolute violation of constraint */
2603 	   SCIP_Real             relviol             /**< relative violation of constraint */
2604 	   )
2605 	{
2606 	   assert(sol != NULL);
2607 	
2608 	   SCIPsolUpdateConsViolation(sol, absviol, relviol);
2609 	   SCIPsolUpdateLPRowViolation(sol, absviol, relviol);
2610 	}
2611 	
2612 	/** get maximum absolute bound violation of solution */
2613 	SCIP_Real SCIPsolGetAbsBoundViolation(
2614 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2615 	   )
2616 	{
2617 	   assert(sol != NULL);
2618 	
2619 	   return sol->viol.absviolbounds;
2620 	}
2621 	
2622 	/** get maximum relative bound violation of solution */
2623 	SCIP_Real SCIPsolGetRelBoundViolation(
2624 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2625 	   )
2626 	{
2627 	   assert(sol != NULL);
2628 	
2629 	   return sol->viol.relviolbounds;
2630 	}
2631 	
2632 	/** get maximum absolute integrality violation of solution */
2633 	SCIP_Real SCIPsolGetAbsIntegralityViolation(
2634 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2635 	   )
2636 	{
2637 	   assert(sol != NULL);
2638 	
2639 	   return sol->viol.absviolintegrality;
2640 	}
2641 	
2642 	/** get maximum absolute LP row violation of solution */
2643 	SCIP_Real SCIPsolGetAbsLPRowViolation(
2644 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2645 	   )
2646 	{
2647 	   assert(sol != NULL);
2648 	
2649 	   return sol->viol.absviollprows;
2650 	}
2651 	
2652 	/** get maximum relative LP row violation of solution */
2653 	SCIP_Real SCIPsolGetRelLPRowViolation(
2654 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2655 	   )
2656 	{
2657 	   assert(sol != NULL);
2658 	
2659 	   return sol->viol.relviollprows;
2660 	}
2661 	
2662 	/** get maximum absolute constraint violation of solution */
2663 	SCIP_Real SCIPsolGetAbsConsViolation(
2664 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2665 	   )
2666 	{
2667 	   assert(sol != NULL);
2668 	
2669 	   return sol->viol.absviolcons;
2670 	}
2671 	
2672 	/** get maximum relative constraint violation of solution */
2673 	SCIP_Real SCIPsolGetRelConsViolation(
2674 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2675 	   )
2676 	{
2677 	   assert(sol != NULL);
2678 	
2679 	   return sol->viol.relviolcons;
2680 	}
2681 	
2682 	/*
2683 	 * simple functions implemented as defines
2684 	 */
2685 	
2686 	/* In debug mode, the following methods are implemented as function calls to ensure
2687 	 * type validity.
2688 	 * In optimized mode, the methods are implemented as defines to improve performance.
2689 	 * However, we want to have them in the library anyways, so we have to undef the defines.
2690 	 */
2691 	
2692 	#undef SCIPsolGetOrigin
2693 	#undef SCIPsolIsOriginal
2694 	#undef SCIPsolGetOrigObj
2695 	#undef SCIPsolGetTime
2696 	#undef SCIPsolGetNodenum
2697 	#undef SCIPsolGetRunnum
2698 	#undef SCIPsolGetDepth
2699 	#undef SCIPsolGetHeur
2700 	#undef SCIPsolGetRelax
2701 	#undef SCIPsolOrigAddObjval
2702 	#undef SCIPsolGetPrimalIndex
2703 	#undef SCIPsolSetPrimalIndex
2704 	#undef SCIPsolGetIndex
2705 	#undef SCIPsolGetType
2706 	#undef SCIPsolSetLPRelaxation
2707 	#undef SCIPsolSetStrongbranching
2708 	#undef SCIPsolSetPseudo
2709 	
2710 	/** gets origin of solution */
2711 	SCIP_SOLORIGIN SCIPsolGetOrigin(
2712 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2713 	   )
2714 	{
2715 	   assert(sol != NULL);
2716 	
2717 	   return sol->solorigin;
2718 	}
2719 	
2720 	/** returns whether the given solution is defined on original variables */
2721 	SCIP_Bool SCIPsolIsOriginal(
2722 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2723 	   )
2724 	{
2725 	   assert(sol != NULL);
2726 	
2727 	   return (sol->solorigin == SCIP_SOLORIGIN_ORIGINAL || sol->solorigin == SCIP_SOLORIGIN_PARTIAL);
2728 	}
2729 	
2730 	/** returns whether the given solution is defined on original variables and containes unknown solution values */
2731 	SCIP_Bool SCIPsolIsPartial(
2732 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2733 	   )
2734 	{
2735 	   assert(sol != NULL);
2736 	
2737 	   return (sol->solorigin == SCIP_SOLORIGIN_PARTIAL);
2738 	}
2739 	
2740 	/** gets objective value of primal CIP solution which lives in the original problem space */
2741 	SCIP_Real SCIPsolGetOrigObj(
2742 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2743 	   )
2744 	{
2745 	   assert(sol != NULL);
2746 	   assert(SCIPsolIsOriginal(sol));
2747 	
2748 	   return sol->obj;
2749 	}
2750 	
2751 	/** adds value to the objective value of a given original primal CIP solution */
2752 	void SCIPsolOrigAddObjval(
2753 	   SCIP_SOL*             sol,                /**< primal CIP solution */
2754 	   SCIP_Real             addval              /**< offset value to add */
2755 	   )
2756 	{
2757 	   assert(sol != NULL);
2758 	   assert(sol->solorigin == SCIP_SOLORIGIN_ORIGINAL);
2759 	
2760 	   sol->obj += addval;
2761 	}
2762 	
2763 	/** gets clock time, when this solution was found */
2764 	SCIP_Real SCIPsolGetTime(
2765 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2766 	   )
2767 	{
2768 	   assert(sol != NULL);
2769 	
2770 	   return sol->time;
2771 	}
2772 	
2773 	/** gets branch and bound run number, where this solution was found */
2774 	int SCIPsolGetRunnum(
2775 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2776 	   )
2777 	{
2778 	   assert(sol != NULL);
2779 	
2780 	   return sol->runnum;
2781 	}
2782 	
2783 	/** gets node number, where this solution was found */
2784 	SCIP_Longint SCIPsolGetNodenum(
2785 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2786 	   )
2787 	{
2788 	   assert(sol != NULL);
2789 	
2790 	   return sol->nodenum;
2791 	}
2792 	
2793 	/** gets node's depth, where this solution was found */
2794 	int SCIPsolGetDepth(
2795 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2796 	   )
2797 	{
2798 	   assert(sol != NULL);
2799 	
2800 	   return sol->depth;
2801 	}
2802 	
2803 	/** gets heuristic, that found this solution or NULL if solution has type different than SCIP_SOLTYPE_HEUR */
2804 	SCIP_HEUR* SCIPsolGetHeur(
2805 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2806 	   )
2807 	{
2808 	   assert(sol != NULL);
2809 	
2810 	   return sol->type == SCIP_SOLTYPE_HEUR ? sol->creator.heur : NULL;
2811 	}
2812 	
2813 	/** gets current position of solution in array of existing solutions of primal data */
2814 	int SCIPsolGetPrimalIndex(
2815 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2816 	   )
2817 	{
2818 	   assert(sol != NULL);
2819 	
2820 	   return sol->primalindex;
2821 	}
2822 	
2823 	/** sets current position of solution in array of existing solutions of primal data */
2824 	void SCIPsolSetPrimalIndex(
2825 	   SCIP_SOL*             sol,                /**< primal CIP solution */
2826 	   int                   primalindex         /**< new primal index of solution */
2827 	   )
2828 	{
2829 	   assert(sol != NULL);
2830 	
2831 	   sol->primalindex = primalindex;
2832 	}
2833 	
2834 	/** returns unique index of given solution */
2835 	int SCIPsolGetIndex(
2836 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2837 	   )
2838 	{
2839 	   assert(sol != NULL);
2840 	
2841 	   return sol->index;
2842 	}
2843 	
2844 	/** informs the solution that it now belongs to the given primal heuristic. For convenience and backwards compatibility,
2845 	 *  the method accepts NULL as input for \p heur, in which case the solution type is set to SCIP_SOLTYPE_LPRELAX.
2846 	 *
2847 	 *  @note Relaxation handlers should use SCIPsolSetRelax() instead.
2848 	 */
2849 	void SCIPsolSetHeur(
2850 	   SCIP_SOL*             sol,                /**< primal CIP solution */
2851 	   SCIP_HEUR*            heur                /**< primal heuristic that found the solution, or NULL for LP solutions */
2852 	   )
2853 	{
2854 	   assert(sol != NULL);
2855 	
2856 	   if( heur == NULL )
2857 	      SCIPsolSetLPRelaxation(sol);
2858 	   else
2859 	   {
2860 	      sol->type = SCIP_SOLTYPE_HEUR;
2861 	      sol->creator.heur = heur;
2862 	   }
2863 	}
2864 	
2865 	/** gets information if solution was found by the LP, a primal heuristic, or a custom relaxator */
2866 	SCIP_SOLTYPE SCIPsolGetType(
2867 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2868 	   )
2869 	{
2870 	   assert(sol != NULL);
2871 	
2872 	   return sol->type;
2873 	}
2874 	
2875 	/** gets relaxation handler that found this solution, or NULL if solution has different type than SCIP_SOLTYPE_RELAX */
2876 	SCIP_RELAX* SCIPsolGetRelax(
2877 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2878 	   )
2879 	{
2880 	   assert(sol != NULL);
2881 	
2882 	   return sol->type == SCIP_SOLTYPE_RELAX ? sol->creator.relax : NULL;
2883 	}
2884 	
2885 	/** informs the solution that it now belongs to the given relaxation handler */
2886 	void SCIPsolSetRelax(
2887 	   SCIP_SOL*             sol,                /**< primal CIP solution */
2888 	   SCIP_RELAX*           relax               /**< relaxator that found the solution */
2889 	   )
2890 	{
2891 	   assert(sol != NULL);
2892 	   assert(relax != NULL);
2893 	
2894 	   sol->type = SCIP_SOLTYPE_RELAX;
2895 	   sol->creator.relax = relax;
2896 	}
2897 	
2898 	/** informs the solution that it is an LP relaxation solution */
2899 	void SCIPsolSetLPRelaxation(
2900 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2901 	   )
2902 	{
2903 	   assert(sol != NULL);
2904 	
2905 	   sol->type = SCIP_SOLTYPE_LPRELAX;
2906 	}
2907 	
2908 	/** informs the solution that it is a solution found during strong branching */
2909 	void SCIPsolSetStrongbranching(
2910 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2911 	   )
2912 	{
2913 	   assert(sol != NULL);
2914 	
2915 	   sol->type = SCIP_SOLTYPE_STRONGBRANCH;
2916 	}
2917 	
2918 	/** informs the solution that it originates from a pseudo solution */
2919 	void SCIPsolSetPseudo(
2920 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2921 	   )
2922 	{
2923 	   assert(sol != NULL);
2924 	
2925 	   sol->type = SCIP_SOLTYPE_PSEUDO;
2926 	}
2927 	
2928