Scippy

SCIP

Solving Constraint Integer Programs

prob.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2014 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file prob.c
17  * @brief Methods and datastructures for storing and manipulating the main problem
18  * @author Tobias Achterberg
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include <assert.h>
24 #include <string.h>
25 
26 #include "scip/def.h"
27 #include "scip/set.h"
28 #include "scip/stat.h"
29 #include "scip/event.h"
30 #include "scip/lp.h"
31 #include "scip/var.h"
32 #include "scip/prob.h"
33 #include "scip/primal.h"
34 #include "scip/tree.h"
35 #include "scip/branch.h"
36 #include "scip/cons.h"
37 #include "scip/pub_message.h"
38 #include "scip/pub_misc.h"
39 
40 
41 #define OBJSCALE_MAXDNOM 1000000LL /**< maximal denominator in objective integral scaling */
42 #define OBJSCALE_MAXSCALE 1000000.0 /**< maximal scalar to reach objective integrality */
43 #define OBJSCALE_MAXFINALSCALE 1000.0 /**< maximal final value to apply as scaling */
44 
45 
46 
47 /*
48  * dymanic memory arrays
49  */
50 
51 /** resizes vars array to be able to store at least num entries */
52 static
54  SCIP_PROB* prob, /**< problem data */
55  SCIP_SET* set, /**< global SCIP settings */
56  int num /**< minimal number of slots in array */
57  )
58 {
59  assert(prob != NULL);
60  assert(set != NULL);
61 
62  if( num > prob->varssize )
63  {
64  int newsize;
65 
66  newsize = SCIPsetCalcMemGrowSize(set, num);
67  SCIP_ALLOC( BMSreallocMemoryArray(&prob->vars, newsize) );
68  prob->varssize = newsize;
69  }
70  assert(num <= prob->varssize);
71 
72  return SCIP_OKAY;
73 }
74 
75 /** resizes fixedvars array to be able to store at least num entries */
76 static
78  SCIP_PROB* prob, /**< problem data */
79  SCIP_SET* set, /**< global SCIP settings */
80  int num /**< minimal number of slots in array */
81  )
82 {
83  assert(prob != NULL);
84  assert(set != NULL);
85 
86  if( num > prob->fixedvarssize )
87  {
88  int newsize;
89 
90  newsize = SCIPsetCalcMemGrowSize(set, num);
91  SCIP_ALLOC( BMSreallocMemoryArray(&prob->fixedvars, newsize) );
92  prob->fixedvarssize = newsize;
93  }
94  assert(num <= prob->fixedvarssize);
95 
96  return SCIP_OKAY;
97 }
98 
99 /** resizes deletedvars array to be able to store at least num entries */
100 static
102  SCIP_PROB* prob, /**< problem data */
103  SCIP_SET* set, /**< global SCIP settings */
104  int num /**< minimal number of slots in array */
105  )
106 {
107  assert(prob != NULL);
108  assert(set != NULL);
109 
110  if( num > prob->deletedvarssize )
111  {
112  int newsize;
113 
114  newsize = SCIPsetCalcMemGrowSize(set, num);
115  SCIP_ALLOC( BMSreallocMemoryArray(&prob->deletedvars, newsize) );
116  prob->deletedvarssize = newsize;
117  }
118  assert(num <= prob->deletedvarssize);
119 
120  return SCIP_OKAY;
121 }
122 
123 /** resizes conss array to be able to store at least num entries */
124 static
126  SCIP_PROB* prob, /**< problem data */
127  SCIP_SET* set, /**< global SCIP settings */
128  int num /**< minimal number of slots in array */
129  )
130 {
131  assert(prob != NULL);
132  assert(set != NULL);
133 
134  if( num > prob->consssize )
135  {
136  int newsize;
137 
138  newsize = SCIPsetCalcMemGrowSize(set, num);
139  SCIP_ALLOC( BMSreallocMemoryArray(&prob->conss, newsize) );
140  prob->consssize = newsize;
141  }
142  assert(num <= prob->consssize);
143 
144  return SCIP_OKAY;
145 }
146 
147 /** returns whether the constraint has a name */
148 static
150  SCIP_CONS* cons /**< constraint */
151  )
152 {
153  const char* name;
154 
155  name = SCIPconsGetName(cons);
156 
157  return (name != NULL && name[0] != '\0');
158 }
159 
160 /** returns whether the variable has a name */
161 static
163  SCIP_VAR* var /**< variable */
164  )
165 {
166  const char* name;
167 
168  name = SCIPvarGetName(var);
169 
170  return (name != NULL && name[0] != '\0');
171 }
172 
173 
174 
175 /*
176  * problem creation
177  */
178 
179 /** creates problem data structure by copying the source problem;
180  * If the problem type requires the use of variable pricers, these pricers should be activated with calls
181  * to SCIPactivatePricer(). These pricers are automatically deactivated, when the problem is freed.
182  */
184  SCIP_PROB** prob, /**< pointer to problem data structure */
185  BMS_BLKMEM* blkmem, /**< block memory */
186  SCIP_SET* set, /**< global SCIP settings */
187  const char* name, /**< problem name */
188  SCIP* sourcescip, /**< source SCIP data structure */
189  SCIP_PROB* sourceprob, /**< source problem structure */
190  SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
191  * target variables */
192  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
193  * target constraints */
194  SCIP_Bool global /**< create a global or a local copy? */
195  )
196 {
197  SCIP_PROBDATA* targetdata;
198  SCIP_RESULT result;
199 
200  assert(prob != NULL);
201  assert(set != NULL);
202  assert(blkmem != NULL);
203  assert(sourcescip != NULL);
204  assert(sourceprob != NULL);
205  assert(varmap != NULL);
206  assert(consmap != NULL);
207 
208  result = SCIP_DIDNOTRUN;
209  targetdata = NULL;
210 
211  /* create problem and initialize callbacks with NULL */
212  SCIP_CALL( SCIPprobCreate(prob, blkmem, set, name, NULL, NULL, NULL, NULL, NULL, NULL, NULL, FALSE) );
213 
214  /* call user copy callback method */
215  if( sourceprob->probdata != NULL && sourceprob->probcopy != NULL )
216  {
217  SCIP_CALL( sourceprob->probcopy(set->scip, sourcescip, sourceprob->probdata, varmap, consmap, &targetdata, global, &result) );
218 
219  /* evaluate result */
220  if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
221  {
222  SCIPerrorMessage("probdata copying method returned invalid result <%d>\n", result);
223  return SCIP_INVALIDRESULT;
224  }
225 
226  assert(targetdata == NULL || result == SCIP_SUCCESS);
227  }
228 
229  /* if copying was successful, add data and callbacks */
230  if( result == SCIP_SUCCESS )
231  {
232  assert( targetdata != NULL );
233  (*prob)->probdelorig = sourceprob->probdelorig;
234  (*prob)->probtrans = sourceprob->probtrans;
235  (*prob)->probdeltrans = sourceprob->probdeltrans;
236  (*prob)->probinitsol = sourceprob->probinitsol;
237  (*prob)->probexitsol = sourceprob->probexitsol;
238  (*prob)->probcopy = sourceprob->probcopy;
239  (*prob)->probdata = targetdata;
240  }
241 
242  return SCIP_OKAY;
243 }
244 
245 /** creates problem data structure
246  * If the problem type requires the use of variable pricers, these pricers should be activated with calls
247  * to SCIPactivatePricer(). These pricers are automatically deactivated, when the problem is freed.
248  */
250  SCIP_PROB** prob, /**< pointer to problem data structure */
251  BMS_BLKMEM* blkmem, /**< block memory */
252  SCIP_SET* set, /**< global SCIP settings */
253  const char* name, /**< problem name */
254  SCIP_DECL_PROBDELORIG ((*probdelorig)), /**< frees user data of original problem */
255  SCIP_DECL_PROBTRANS ((*probtrans)), /**< creates user data of transformed problem by transforming original user data */
256  SCIP_DECL_PROBDELTRANS((*probdeltrans)), /**< frees user data of transformed problem */
257  SCIP_DECL_PROBINITSOL ((*probinitsol)), /**< solving process initialization method of transformed data */
258  SCIP_DECL_PROBEXITSOL ((*probexitsol)), /**< solving process deinitialization method of transformed data */
259  SCIP_DECL_PROBCOPY ((*probcopy)), /**< copies user data if you want to copy it to a subscip, or NULL */
260  SCIP_PROBDATA* probdata, /**< user problem data set by the reader */
261  SCIP_Bool transformed /**< is this the transformed problem? */
262  )
263 {
264  assert(prob != NULL);
265 
266  SCIP_ALLOC( BMSallocMemory(prob) );
267  SCIP_ALLOC( BMSduplicateMemoryArray(&(*prob)->name, name, strlen(name)+1) );
268 
269  (*prob)->probdata = probdata;
270  (*prob)->probcopy = probcopy;
271  (*prob)->probdelorig = probdelorig;
272  (*prob)->probtrans = probtrans;
273  (*prob)->probdeltrans = probdeltrans;
274  (*prob)->probinitsol = probinitsol;
275  (*prob)->probexitsol = probexitsol;
276  if( set->misc_usevartable )
277  {
278  SCIP_CALL( SCIPhashtableCreate(&(*prob)->varnames, blkmem,
279  (set->misc_usesmalltables ? SCIP_HASHSIZE_NAMES_SMALL : SCIP_HASHSIZE_NAMES),
280  SCIPhashGetKeyVar, SCIPhashKeyEqString, SCIPhashKeyValString, NULL) );
281  }
282  else
283  (*prob)->varnames = NULL;
284  (*prob)->vars = NULL;
285  (*prob)->varssize = 0;
286  (*prob)->nvars = 0;
287  (*prob)->nbinvars = 0;
288  (*prob)->nintvars = 0;
289  (*prob)->nimplvars = 0;
290  (*prob)->ncontvars = 0;
291  (*prob)->ncolvars = 0;
292  (*prob)->fixedvars = NULL;
293  (*prob)->fixedvarssize = 0;
294  (*prob)->nfixedvars = 0;
295  (*prob)->deletedvars = NULL;
296  (*prob)->deletedvarssize = 0;
297  (*prob)->ndeletedvars = 0;
298  (*prob)->nobjvars = 0;
299  if( set->misc_useconstable )
300  {
301  SCIP_CALL( SCIPhashtableCreate(&(*prob)->consnames, blkmem,
302  (set->misc_usesmalltables ? SCIP_HASHSIZE_NAMES_SMALL : SCIP_HASHSIZE_NAMES),
303  SCIPhashGetKeyCons, SCIPhashKeyEqString, SCIPhashKeyValString, NULL) );
304  }
305  else
306  (*prob)->consnames = NULL;
307  (*prob)->conss = NULL;
308  (*prob)->consssize = 0;
309  (*prob)->nconss = 0;
310  (*prob)->maxnconss = 0;
311  (*prob)->startnvars = 0;
312  (*prob)->startnconss = 0;
313  (*prob)->objsense = SCIP_OBJSENSE_MINIMIZE;
314  (*prob)->objoffset = 0.0;
315  (*prob)->objscale = 1.0;
316  (*prob)->objlim = SCIP_INVALID;
317  (*prob)->dualbound = SCIP_INVALID;
318  (*prob)->objisintegral = FALSE;
319  (*prob)->transformed = transformed;
320 
321  return SCIP_OKAY;
322 }
323 
324 /** sets callback to free user data of original problem */
326  SCIP_PROB* prob, /**< problem */
327  SCIP_DECL_PROBDELORIG ((*probdelorig)) /**< frees user data of original problem */
328  )
329 {
330  assert(prob != NULL);
331 
332  prob->probdelorig = probdelorig;
333 }
334 
335 /** sets callback to create user data of transformed problem by transforming original user data */
337  SCIP_PROB* prob, /**< problem */
338  SCIP_DECL_PROBTRANS ((*probtrans)) /**< creates user data of transformed problem by transforming original user data */
339  )
340 {
341  assert(prob != NULL);
342 
343  prob->probtrans = probtrans;
344 }
345 
346 /** sets callback to free user data of transformed problem */
348  SCIP_PROB* prob, /**< problem */
349  SCIP_DECL_PROBDELTRANS((*probdeltrans)) /**< frees user data of transformed problem */
350  )
351 {
352  assert(prob != NULL);
353 
354  prob->probdeltrans = probdeltrans;
355 }
356 
357 /** sets solving process initialization callback of transformed data */
359  SCIP_PROB* prob, /**< problem */
360  SCIP_DECL_PROBINITSOL ((*probinitsol)) /**< solving process initialization callback of transformed data */
361  )
362 {
363  assert(prob != NULL);
364 
365  prob->probinitsol= probinitsol;
366 }
367 
368 /** sets solving process deinitialization callback of transformed data */
370  SCIP_PROB* prob, /**< problem */
371  SCIP_DECL_PROBEXITSOL ((*probexitsol)) /**< solving process deinitialization callback of transformed data */
372  )
373 {
374  assert(prob != NULL);
375 
376  prob->probexitsol= probexitsol;
377 }
378 
379 /** sets callback to copy user data to copy it to a subscip, or NULL */
381  SCIP_PROB* prob, /**< problem */
382  SCIP_DECL_PROBCOPY ((*probcopy)) /**< copies user data if you want to copy it to a subscip, or NULL */
383  )
384 {
385  assert(prob != NULL);
386 
387  prob->probcopy= probcopy;
388 }
389 
390 /** frees problem data structure */
392  SCIP_PROB** prob, /**< pointer to problem data structure */
393  BMS_BLKMEM* blkmem, /**< block memory buffer */
394  SCIP_SET* set, /**< global SCIP settings */
395  SCIP_STAT* stat, /**< dynamic problem statistics */
396  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
397  SCIP_LP* lp /**< current LP data (or NULL, if it's the original problem) */
398  )
399 {
400  int v;
401 
402  assert(prob != NULL);
403  assert(*prob != NULL);
404  assert(set != NULL);
405 
406  /* remove all constraints from the problem */
407  while( (*prob)->nconss > 0 )
408  {
409  /*@todo for debug mode it even might sense, to sort them downwards after their arraypos */
410  assert((*prob)->conss != NULL);
411  SCIP_CALL( SCIPprobDelCons(*prob, blkmem, set, stat, (*prob)->conss[(*prob)->nconss - 1]) );
412  }
413 
414  if( (*prob)->transformed )
415  {
416  int h;
417 
418  /* unlock variables for all constraint handlers that don't need constraints */
419  for( h = 0; h < set->nconshdlrs; ++h )
420  {
421  if( !SCIPconshdlrNeedsCons(set->conshdlrs[h]) )
422  {
423  SCIP_CALL( SCIPconshdlrUnlockVars(set->conshdlrs[h], set) );
424  }
425  }
426  }
427 
428  /* free constraint array */
429  BMSfreeMemoryArrayNull(&(*prob)->conss);
430 
431  /* free user problem data */
432  if( (*prob)->transformed )
433  {
434  if( (*prob)->probdeltrans != NULL )
435  {
436  SCIP_CALL( (*prob)->probdeltrans(set->scip, &(*prob)->probdata) );
437  }
438  }
439  else
440  {
441  if( (*prob)->probdelorig != NULL )
442  {
443  SCIP_CALL( (*prob)->probdelorig(set->scip, &(*prob)->probdata) );
444  }
445  }
446 
447  /* release problem variables */
448  for( v = (*prob)->nvars - 1; v >= 0; --v )
449  {
450  assert(SCIPvarGetProbindex((*prob)->vars[v]) >= 0);
451  SCIP_CALL( SCIPvarRemove((*prob)->vars[v], blkmem, set, TRUE) );
452  SCIP_CALL( SCIPvarRelease(&(*prob)->vars[v], blkmem, set, eventqueue, lp) );
453  }
454  BMSfreeMemoryArrayNull(&(*prob)->vars);
455 
456  /* release fixed problem variables */
457  for( v = (*prob)->nfixedvars - 1; v >= 0; --v )
458  {
459  assert(SCIPvarGetProbindex((*prob)->fixedvars[v]) == -1);
460  SCIP_CALL( SCIPvarRelease(&(*prob)->fixedvars[v], blkmem, set, eventqueue, lp) );
461  }
462  BMSfreeMemoryArrayNull(&(*prob)->fixedvars);
463 
464  /* free deleted problem variables array */
465  BMSfreeMemoryArrayNull(&(*prob)->deletedvars);
466 
467  /* free hash tables for names */
468  if( (*prob)->varnames != NULL )
469  {
470  SCIPhashtableFree(&(*prob)->varnames);
471  }
472  if( (*prob)->consnames != NULL )
473  {
474  SCIPhashtableFree(&(*prob)->consnames);
475  }
476  BMSfreeMemoryArray(&(*prob)->name);
477  BMSfreeMemory(prob);
478 
479  return SCIP_OKAY;
480 }
481 
482 /** transform problem data into normalized form */
484  SCIP_PROB* source, /**< problem to transform */
485  BMS_BLKMEM* blkmem, /**< block memory buffer */
486  SCIP_SET* set, /**< global SCIP settings */
487  SCIP_STAT* stat, /**< problem statistics */
488  SCIP_PRIMAL* primal, /**< primal data */
489  SCIP_TREE* tree, /**< branch and bound tree */
490  SCIP_LP* lp, /**< current LP data */
491  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
492  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
493  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
494  SCIP_PROB** target /**< pointer to target problem data structure */
495  )
496 {
497  SCIP_VAR* targetvar;
498  SCIP_CONS* targetcons;
499  char transname[SCIP_MAXSTRLEN];
500  int v;
501  int c;
502  int h;
503 
504  assert(set != NULL);
505  assert(source != NULL);
506  assert(blkmem != NULL);
507  assert(target != NULL);
508 
509  SCIPdebugMessage("transform problem: original has %d variables\n", source->nvars);
510 
511  /* create target problem data (probdelorig and probtrans are not needed, probdata is set later) */
512  (void) SCIPsnprintf(transname, SCIP_MAXSTRLEN, "t_%s", source->name);
513  SCIP_CALL( SCIPprobCreate(target, blkmem, set, transname, source->probdelorig, source->probtrans, source->probdeltrans,
514  source->probinitsol, source->probexitsol, source->probcopy, NULL, TRUE) );
515  SCIPprobSetObjsense(*target, source->objsense);
516 
517  /* transform objective limit */
518  if( source->objlim < SCIP_INVALID )
519  SCIPprobSetObjlim(*target, source->objlim);
520 
521  /* transform dual bound */
522  if( source->dualbound < SCIP_INVALID )
523  SCIPprobSetDualbound(*target, source->dualbound);
524 
525  /* transform and copy all variables to target problem */
526  SCIP_CALL( probEnsureVarsMem(*target, set, source->nvars) );
527  for( v = 0; v < source->nvars; ++v )
528  {
529  SCIP_CALL( SCIPvarTransform(source->vars[v], blkmem, set, stat, source->objsense, &targetvar) );
530  SCIP_CALL( SCIPprobAddVar(*target, blkmem, set, lp, branchcand, eventfilter, eventqueue, targetvar) );
531  SCIP_CALL( SCIPvarRelease(&targetvar, blkmem, set, eventqueue, NULL) );
532  }
533  assert((*target)->nvars == source->nvars);
534  assert((*target)->nobjvars == SCIPprobGetNObjVars(*target, set));
535 
536  /* call user data transformation */
537  if( source->probtrans != NULL )
538  {
539  SCIP_CALL( source->probtrans(set->scip, source->probdata, &(*target)->probdata) );
540  }
541  else
542  (*target)->probdata = source->probdata;
543 
544  /* transform and copy all constraints to target problem */
545  for( c = 0; c < source->nconss; ++c )
546  {
547  SCIP_CALL( SCIPconsTransform(source->conss[c], blkmem, set, &targetcons) );
548  SCIP_CALL( SCIPprobAddCons(*target, set, stat, targetcons) );
549  SCIP_CALL( SCIPconsRelease(&targetcons, blkmem, set) );
550  }
551 
552  /* lock variables for all constraint handlers that don't need constraints */
553  for( h = 0; h < set->nconshdlrs; ++h )
554  {
555  if( !SCIPconshdlrNeedsCons(set->conshdlrs[h]) )
556  {
557  SCIP_CALL( SCIPconshdlrLockVars(set->conshdlrs[h], set) );
558  }
559  }
560 
561  /* objective value is always integral, iff original objective value is always integral and shift is integral */
562  (*target)->objisintegral = source->objisintegral && SCIPsetIsIntegral(set, (*target)->objoffset);
563 
564  /* check, whether objective value is always integral by inspecting the problem, if it is the case adjust the
565  * cutoff bound if primal solution is already known
566  */
567  SCIP_CALL( SCIPprobCheckObjIntegral(*target, source, blkmem, set, stat, primal, tree, lp, eventqueue) );
568 
569  return SCIP_OKAY;
570 }
571 
572 /** resets the global and local bounds of original variables in original problem to their original values */
574  SCIP_PROB* prob, /**< original problem data */
575  BMS_BLKMEM* blkmem, /**< block memory */
576  SCIP_SET* set, /**< global SCIP settings */
577  SCIP_STAT* stat /**< problem statistics */
578  )
579 {
580  int v;
581 
582  assert(prob != NULL);
583  assert(!prob->transformed);
584  assert(prob->nfixedvars == 0);
585 
586  for( v = 0; v < prob->nvars; ++v )
587  {
588  SCIP_CALL( SCIPvarResetBounds(prob->vars[v], blkmem, set, stat) );
589  }
590 
591  return SCIP_OKAY;
592 }
593 
594 /** (Re)Sort the variables, which appear in the four categories (binary, integer, implicit, continuous) after presolve
595  * with respect to their original index (within their categories). Adjust the problem index afterwards which is
596  * supposed to reflect the position in the variable array. This additional (re)sorting is supposed to get more robust
597  * against the order presolving fixed variables. (We also reobtain a possible block structure induced by the user
598  * model)
599  */
601  SCIP_PROB* prob /**< problem data */
602  )
603 {
604  SCIP_VAR** vars;
605  int nbinvars;
606  int nintvars;
607  int nimplvars;
608  int ncontvars;
609  int nvars;
610  int v;
611 
612  vars = prob->vars;
613  nvars = prob->nvars;
614  nbinvars = prob->nbinvars;
615  nintvars = prob->nintvars;
616  nimplvars = prob->nimplvars;
617  ncontvars = prob->ncontvars;
618 
619  if( nvars == 0 )
620  return;
621 
622  assert(vars != NULL);
623  assert(nbinvars + nintvars + nimplvars + ncontvars == nvars);
624 
625  SCIPdebugMessage("entering sorting with respect to original block structure! \n");
626 
627  /* sort binaries */
628  if( nbinvars > 0 )
629  SCIPsortPtr((void**)vars, SCIPvarComp, nbinvars);
630 
631  /* sort integers */
632  if( nintvars > 0 )
633  SCIPsortPtr((void**)&vars[nbinvars], SCIPvarComp, nintvars);
634 
635  /* sort implicit variables */
636  if( nimplvars > 0 )
637  SCIPsortPtr((void**)&vars[nbinvars + nintvars], SCIPvarComp, nimplvars);
638 
639  /* sort continuous variables*/
640  if( ncontvars > 0 )
641  SCIPsortPtr((void**)&vars[nbinvars + nintvars + nimplvars], SCIPvarComp, ncontvars);
642 
643  /* after sorting, the problem index of each variable has to be adjusted */
644  for( v = 0; v < nvars; ++v )
645  {
646  vars[v]->probindex = v;
647  SCIPdebugMessage("Variable: Problem index <%d>, original index <%d> \n", vars[v]->probindex, vars[v]->index);
648  }
649 }
650 
651 
652 
653 /*
654  * problem modification
655  */
656 
657 /** sets user problem data */
659  SCIP_PROB* prob, /**< problem */
660  SCIP_PROBDATA* probdata /**< user problem data to use */
661  )
662 {
663  assert(prob != NULL);
664 
665  prob->probdata = probdata;
666 }
667 
668 /** inserts variable at the correct position in vars array, depending on its type */
669 static
671  SCIP_PROB* prob, /**< problem data */
672  SCIP_VAR* var /**< variable to insert */
673  )
674 {
675  int insertpos;
676  int intstart;
677  int implstart;
678  int contstart;
679 
680  assert(prob != NULL);
681  assert(prob->vars != NULL);
682  assert(prob->nvars < prob->varssize);
683  assert(var != NULL);
684  assert(SCIPvarGetProbindex(var) == -1);
688  /* original variables cannot go into transformed problem and transformed variables cannot go into original problem */
689  assert((SCIPvarGetStatus(var) != SCIP_VARSTATUS_ORIGINAL) == prob->transformed);
690 
691  /* insert variable in array */
692  insertpos = prob->nvars;
693  intstart = prob->nbinvars;
694  implstart = intstart + prob->nintvars;
695  contstart = implstart + prob->nimplvars;
696 
698  prob->ncontvars++;
699  else
700  {
701  if( insertpos > contstart )
702  {
703  prob->vars[insertpos] = prob->vars[contstart];
704  SCIPvarSetProbindex(prob->vars[insertpos], insertpos);
705  insertpos = contstart;
706  }
707  assert(insertpos == contstart);
708 
710  prob->nimplvars++;
711  else
712  {
713  if( insertpos > implstart )
714  {
715  prob->vars[insertpos] = prob->vars[implstart];
716  SCIPvarSetProbindex(prob->vars[insertpos], insertpos);
717  insertpos = implstart;
718  }
719  assert(insertpos == implstart);
720 
722  prob->nintvars++;
723  else
724  {
725  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
726  if( insertpos > intstart )
727  {
728  prob->vars[insertpos] = prob->vars[intstart];
729  SCIPvarSetProbindex(prob->vars[insertpos], insertpos);
730  insertpos = intstart;
731  }
732  assert(insertpos == intstart);
733 
734  prob->nbinvars++;
735  }
736  }
737  }
738  prob->nvars++;
739 
740  assert(prob->nvars == prob->nbinvars + prob->nintvars + prob->nimplvars + prob->ncontvars);
741  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && insertpos == prob->nbinvars - 1)
742  || (SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER && insertpos == prob->nbinvars + prob->nintvars - 1)
743  || (SCIPvarGetType(var) == SCIP_VARTYPE_IMPLINT && insertpos == prob->nbinvars + prob->nintvars + prob->nimplvars - 1)
745  && insertpos == prob->nbinvars + prob->nintvars + prob->nimplvars + prob->ncontvars - 1));
746 
747  prob->vars[insertpos] = var;
748  SCIPvarSetProbindex(var, insertpos);
749 
750  /* update number of column variables in problem */
752  prob->ncolvars++;
753  assert(0 <= prob->ncolvars && prob->ncolvars <= prob->nvars);
754 }
755 
756 /** removes variable from vars array */
757 static
759  SCIP_PROB* prob, /**< problem data */
760  BMS_BLKMEM* blkmem, /**< block memory */
761  SCIP_SET* set, /**< global SCIP settings */
762  SCIP_VAR* var /**< variable to remove */
763  )
764 {
765  int freepos;
766  int intstart;
767  int implstart;
768  int contstart;
769 
770  assert(prob != NULL);
771  assert(var != NULL);
772  assert(SCIPvarGetProbindex(var) >= 0);
773  assert(prob->vars != NULL);
774  assert(prob->vars[SCIPvarGetProbindex(var)] == var);
775 
776  intstart = prob->nbinvars;
777  implstart = intstart + prob->nintvars;
778  contstart = implstart + prob->nimplvars;
779 
780  switch( SCIPvarGetType(var) )
781  {
782  case SCIP_VARTYPE_BINARY:
783  assert(0 <= SCIPvarGetProbindex(var) && SCIPvarGetProbindex(var) < intstart);
784  prob->nbinvars--;
785  break;
787  assert(intstart <= SCIPvarGetProbindex(var) && SCIPvarGetProbindex(var) < implstart);
788  prob->nintvars--;
789  break;
791  assert(implstart <= SCIPvarGetProbindex(var) && SCIPvarGetProbindex(var) < contstart);
792  prob->nimplvars--;
793  break;
795  assert(contstart <= SCIPvarGetProbindex(var) && SCIPvarGetProbindex(var) < prob->nvars);
796  prob->ncontvars--;
797  break;
798  default:
799  SCIPerrorMessage("unknown variable type\n");
800  SCIPABORT();
801  return SCIP_INVALIDDATA; /*lint !e527*/
802  }
803 
804  /* move last binary, last integer, last implicit, and last continuous variable forward to fill the free slot */
805  freepos = SCIPvarGetProbindex(var);
806  if( freepos < intstart-1 )
807  {
808  /* move last binary variable to free slot */
809  prob->vars[freepos] = prob->vars[intstart-1];
810  SCIPvarSetProbindex(prob->vars[freepos], freepos);
811  freepos = intstart-1;
812  }
813  if( freepos < implstart-1 )
814  {
815  /* move last integer variable to free slot */
816  prob->vars[freepos] = prob->vars[implstart-1];
817  SCIPvarSetProbindex(prob->vars[freepos], freepos);
818  freepos = implstart-1;
819  }
820  if( freepos < contstart-1 )
821  {
822  /* move last implicit integer variable to free slot */
823  prob->vars[freepos] = prob->vars[contstart-1];
824  SCIPvarSetProbindex(prob->vars[freepos], freepos);
825  freepos = contstart-1;
826  }
827  if( freepos < prob->nvars-1 )
828  {
829  /* move last implicit integer variable to free slot */
830  prob->vars[freepos] = prob->vars[prob->nvars-1];
831  SCIPvarSetProbindex(prob->vars[freepos], freepos);
832  freepos = prob->nvars-1;
833  }
834  assert(freepos == prob->nvars-1);
835 
836  prob->nvars--;
837  assert(prob->nvars == prob->nbinvars + prob->nintvars + prob->nimplvars + prob->ncontvars);
838 
839  /* update number of column variables in problem */
841  prob->ncolvars--;
842  assert(0 <= prob->ncolvars && prob->ncolvars <= prob->nvars);
843 
844  /* inform the variable that it is no longer in the problem; if necessary, delete it from the implication graph */
845  SCIP_CALL( SCIPvarRemove(var, blkmem, set, FALSE) );
846 
847  return SCIP_OKAY;
848 }
849 
850 /** adds variable's name to the namespace */
852  SCIP_PROB* prob, /**< problem data */
853  SCIP_VAR* var /**< variable */
854  )
855 {
856  assert(SCIPvarGetProbindex(var) != -1);
857 
858  if( varHasName(var) && prob->varnames != NULL )
859  {
860  SCIP_CALL( SCIPhashtableInsert(prob->varnames, (void*)var) );
861  }
862 
863  return SCIP_OKAY;
864 }
865 
866 /** removes variable's name from the namespace */
868  SCIP_PROB* prob, /**< problem data */
869  SCIP_VAR* var /**< variable */
870  )
871 {
872  if( varHasName(var) && prob->varnames != NULL )
873  {
874  assert(SCIPhashtableExists(prob->varnames, (void*)var));
875  SCIP_CALL( SCIPhashtableRemove(prob->varnames, (void*)var) );
876  }
877 
878  return SCIP_OKAY;
879 }
880 
881 /** adds variable to the problem and captures it */
883  SCIP_PROB* prob, /**< problem data */
884  BMS_BLKMEM* blkmem, /**< block memory buffers */
885  SCIP_SET* set, /**< global SCIP settings */
886  SCIP_LP* lp, /**< current LP data */
887  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
888  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
889  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
890  SCIP_VAR* var /**< variable to add */
891  )
892 {
893  assert(prob != NULL);
894  assert(set != NULL);
895  assert(var != NULL);
896  assert(SCIPvarGetProbindex(var) == -1);
900  /* original variables cannot go into transformed problem and transformed variables cannot go into original problem */
901  assert((SCIPvarGetStatus(var) != SCIP_VARSTATUS_ORIGINAL) == prob->transformed);
902 
903 #ifndef NDEBUG
904  /* check if we add this variables to the same scip, where we created it */
905  if( var->scip != set->scip )
906  {
907  SCIPerrorMessage("variable belongs to a different scip instance\n");
908  return SCIP_INVALIDDATA;
909  }
910 #endif
911 
912  /* capture variable */
913  SCIPvarCapture(var);
914 
915  /* allocate additional memory */
916  SCIP_CALL( probEnsureVarsMem(prob, set, prob->nvars+1) );
917 
918  /* insert variable in vars array and mark it to be in problem */
919  probInsertVar(prob, var);
920 
921  /* add variable's name to the namespace */
922  SCIP_CALL( SCIPprobAddVarName(prob, var) );
923 
924  /* update branching candidates and pseudo and loose objective value in the LP */
926  {
927  SCIP_CALL( SCIPbranchcandUpdateVar(branchcand, set, var) );
928  SCIP_CALL( SCIPlpUpdateAddVar(lp, set, var) );
929  }
930 
931  SCIPdebugMessage("added variable <%s> to problem (%d variables: %d binary, %d integer, %d implicit, %d continuous)\n",
932  SCIPvarGetName(var), prob->nvars, prob->nbinvars, prob->nintvars, prob->nimplvars, prob->ncontvars);
933 
934  if( prob->transformed )
935  {
936  SCIP_EVENT* event;
937 
938  /* issue VARADDED event */
939  SCIP_CALL( SCIPeventCreateVarAdded(&event, blkmem, var) );
940  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
941 
942  /* update the number of variables with non-zero objective coefficient */
943  SCIPprobUpdateNObjVars(prob, set, 0.0, SCIPvarGetObj(var));
944  }
945 
946  return SCIP_OKAY;
947 }
948 
949 /** marks variable to be removed from the problem; however, the variable is NOT removed from the constraints */
951  SCIP_PROB* prob, /**< problem data */
952  BMS_BLKMEM* blkmem, /**< block memory */
953  SCIP_SET* set, /**< global SCIP settings */
954  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
955  SCIP_VAR* var, /**< problem variable */
956  SCIP_Bool* deleted /**< pointer to store whether marking variable to be deleted was successful */
957  )
958 {
959  assert(prob != NULL);
960  assert(set != NULL);
961  assert(var != NULL);
962  assert(deleted != NULL);
963  assert(SCIPvarGetProbindex(var) != -1);
967 
968  *deleted = FALSE;
969 
970  /* don't remove variables that are not in the problem */
971  /**@todo what about negated variables? should the negation variable be removed instead? */
972  if( SCIPvarGetProbindex(var) == -1 )
973  return SCIP_OKAY;
974 
975  /* don't remove the direct counterpart of an original variable from the transformed problem, because otherwise
976  * operations on the original variables would be applied to a NULL pointer
977  */
978  if( SCIPvarIsTransformedOrigvar(var) )
979  return SCIP_OKAY;
980 
981  assert(SCIPvarGetNegatedVar(var) == NULL);
982 
983  SCIPdebugMessage("deleting variable <%s> from problem (%d variables: %d binary, %d integer, %d implicit, %d continuous)\n",
984  SCIPvarGetName(var), prob->nvars, prob->nbinvars, prob->nintvars, prob->nimplvars, prob->ncontvars);
985 
986  /* mark variable to be deleted from the problem */
987  SCIPvarMarkDeleted(var);
988 
989  if( prob->transformed )
990  {
991  SCIP_EVENT* event;
992 
993  assert(eventqueue != NULL);
994 
995  /* issue VARDELETED event */
996  SCIP_CALL( SCIPeventCreateVarDeleted(&event, blkmem, var) );
997  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
998  }
999 
1000  /* remember that the variable should be deleted from the problem in SCIPprobPerformVarDeletions() */
1001  SCIP_CALL( probEnsureDeletedvarsMem(prob, set, prob->ndeletedvars+1) );
1002  prob->deletedvars[prob->ndeletedvars] = var;
1003  prob->ndeletedvars++;
1004 
1005  *deleted = TRUE;
1006 
1007  return SCIP_OKAY;
1008 }
1009 
1010 /** actually removes the deleted variables from the problem and releases them */
1012  SCIP_PROB* prob, /**< problem data */
1013  BMS_BLKMEM* blkmem, /**< block memory */
1014  SCIP_SET* set, /**< global SCIP settings */
1015  SCIP_STAT* stat, /**< dynamic problem statistics */
1016  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1017  SCIP_LP* lp, /**< current LP data (may be NULL) */
1018  SCIP_BRANCHCAND* branchcand /**< branching candidate storage */
1019  )
1020 {
1021  int i;
1022 
1023  assert(prob != NULL);
1024  assert(set != NULL);
1025 
1026  /* delete variables from the constraints;
1027  * do this only in solving stage, in presolving, it is already handled by the constraint handlers
1028  */
1029  if( SCIPsetGetStage(set) == SCIP_STAGE_SOLVING )
1030  {
1031  for( i = 0; i < set->nconshdlrs; ++i )
1032  {
1033  SCIP_CALL( SCIPconshdlrDelVars(set->conshdlrs[i], blkmem, set, stat) );
1034  }
1035  }
1036 
1037  for( i = 0; i < prob->ndeletedvars; ++i )
1038  {
1039  SCIP_VAR* var;
1040 
1041  var = prob->deletedvars[i];
1042 
1043  /* don't delete the variable, if it was fixed or aggregated in the meantime */
1044  if( SCIPvarGetProbindex(var) >= 0 )
1045  {
1046  SCIPdebugMessage("perform deletion of <%s> [%p]\n", SCIPvarGetName(var), (void*)var);
1047 
1048  /* convert column variable back into loose variable, free LP column */
1050  {
1051  SCIP_CALL( SCIPvarLoose(var, blkmem, set, eventqueue, prob, lp) );
1052  }
1053 
1054  /* update branching candidates and pseudo and loose objective value in the LP */
1056  {
1057  SCIP_CALL( SCIPlpUpdateDelVar(lp, set, var) );
1058  SCIP_CALL( SCIPbranchcandRemoveVar(branchcand, var) );
1059  }
1060 
1061  /* remove variable's name from the namespace */
1062  SCIP_CALL( SCIPprobRemoveVarName(prob, var) );
1063 
1064  /* remove variable from vars array and mark it to be not in problem */
1065  SCIP_CALL( probRemoveVar(prob, blkmem, set, var) );
1066 
1067  /* update the number of variables with non-zero objective coefficient */
1068  if( prob->transformed )
1069  SCIPprobUpdateNObjVars(prob, set, SCIPvarGetObj(var), 0.0);
1070 
1071  /* release variable */
1072  SCIP_CALL( SCIPvarRelease(&prob->deletedvars[i], blkmem, set, eventqueue, lp) );
1073  }
1074  }
1075  prob->ndeletedvars = 0;
1076 
1077  return SCIP_OKAY;
1078 }
1079 
1080 /** changes the type of a variable in the problem */
1082  SCIP_PROB* prob, /**< problem data */
1083  BMS_BLKMEM* blkmem, /**< block memory */
1084  SCIP_SET* set, /**< global SCIP settings */
1085  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1086  SCIP_VAR* var, /**< variable to add */
1087  SCIP_VARTYPE vartype /**< new type of variable */
1088  )
1089 {
1090  assert(prob != NULL);
1091  assert(var != NULL);
1092  assert(SCIPvarGetProbindex(var) >= 0);
1096  assert(branchcand != NULL || SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
1097 
1098  if( SCIPvarGetType(var) == vartype )
1099  return SCIP_OKAY;
1100 
1101  /* temporarily remove variable from branching candidates */
1102  if( branchcand != NULL )
1103  {
1104  SCIP_CALL( SCIPbranchcandRemoveVar(branchcand, var) );
1105  }
1106 
1107  /* temporarily remove variable from problem */
1108  SCIP_CALL( probRemoveVar(prob, blkmem, set, var) );
1109 
1110  /* change the type of the variable */
1111  SCIP_CALL( SCIPvarChgType(var, vartype) );
1112 
1113  /* reinsert variable into problem */
1114  probInsertVar(prob, var);
1115 
1116  /* update branching candidates */
1117  if( branchcand != NULL )
1118  {
1119  SCIP_CALL( SCIPbranchcandUpdateVar(branchcand, set, var) );
1120  }
1121 
1122  return SCIP_OKAY;
1123 }
1124 
1125 /** informs problem, that the given loose problem variable changed its status */
1127  SCIP_PROB* prob, /**< problem data */
1128  BMS_BLKMEM* blkmem, /**< block memory */
1129  SCIP_SET* set, /**< global SCIP settings */
1130  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1131  SCIP_VAR* var /**< problem variable */
1132  )
1133 {
1134  assert(prob != NULL);
1135  assert(var != NULL);
1136  assert(SCIPvarGetProbindex(var) != -1);
1137 
1138  /* get current status of variable */
1139  switch( SCIPvarGetStatus(var) )
1140  {
1142  SCIPerrorMessage("variables cannot switch to ORIGINAL status\n");
1143  return SCIP_INVALIDDATA;
1144 
1145  case SCIP_VARSTATUS_LOOSE:
1146  /* variable switched from column to loose */
1147  prob->ncolvars--;
1148  break;
1149 
1150  case SCIP_VARSTATUS_COLUMN:
1151  /* variable switched from non-column to column */
1152  prob->ncolvars++;
1153  break;
1154 
1155  case SCIP_VARSTATUS_FIXED:
1159  /* variable switched from unfixed to fixed (if it was fixed before, probindex would have been -1) */
1160 
1161  /* remove variable from problem */
1162  SCIP_CALL( probRemoveVar(prob, blkmem, set, var) );
1163 
1164  /* insert variable in fixedvars array */
1165  SCIP_CALL( probEnsureFixedvarsMem(prob, set, prob->nfixedvars+1) );
1166  prob->fixedvars[prob->nfixedvars] = var;
1167  prob->nfixedvars++;
1168 
1169  /* update branching candidates */
1170  SCIP_CALL( SCIPbranchcandUpdateVar(branchcand, set, var) );
1171  break;
1172 
1173  default:
1174  SCIPerrorMessage("invalid variable status <%d>\n", SCIPvarGetStatus(var));
1175  return SCIP_INVALIDDATA;
1176  }
1177  assert(0 <= prob->ncolvars && prob->ncolvars <= prob->nvars);
1178 
1179  return SCIP_OKAY;
1180 }
1181 
1182 /** adds constraint's name to the namespace */
1184  SCIP_PROB* prob, /**< problem data */
1185  SCIP_CONS* cons /**< constraint */
1186  )
1187 {
1188  /* add constraint's name to the namespace */
1189  if( consHasName(cons) && prob->consnames != NULL )
1190  {
1191  SCIP_CALL( SCIPhashtableInsert(prob->consnames, (void*)cons) );
1192  }
1193 
1194  return SCIP_OKAY;
1195 }
1196 
1197 /** remove constraint's name from the namespace */
1199  SCIP_PROB* prob, /**< problem data */
1200  SCIP_CONS* cons /**< constraint */
1201  )
1202 {
1203  /* remove constraint's name from the namespace */
1204  if( consHasName(cons) && prob->consnames != NULL )
1205  {
1206  assert(SCIPhashtableExists(prob->consnames, (void*)cons));
1207  SCIP_CALL( SCIPhashtableRemove(prob->consnames, (void*)cons) );
1208  }
1209 
1210  return SCIP_OKAY;
1211 }
1212 
1213 /** adds constraint to the problem and captures it;
1214  * a local constraint is automatically upgraded into a global constraint
1215  */
1217  SCIP_PROB* prob, /**< problem data */
1218  SCIP_SET* set, /**< global SCIP settings */
1219  SCIP_STAT* stat, /**< dynamic problem statistics */
1220  SCIP_CONS* cons /**< constraint to add */
1221  )
1222 {
1223  assert(prob != NULL);
1224  assert(cons != NULL);
1225  assert(cons->addconssetchg == NULL);
1226  assert(cons->addarraypos == -1);
1227 
1228 #ifndef NDEBUG
1229  /* check if we add this constraint to the same scip, where we create the constraint */
1230  if( cons->scip != set->scip )
1231  {
1232  SCIPerrorMessage("constraint belongs to different scip instance\n");
1233  return SCIP_INVALIDDATA;
1234  }
1235 #endif
1236  SCIPdebugMessage("adding constraint <%s> to global problem -> %d constraints\n",
1237  SCIPconsGetName(cons), prob->nconss+1);
1238 
1239  /* mark the constraint as problem constraint, and remember the constraint's position */
1240  cons->addconssetchg = NULL;
1241  cons->addarraypos = prob->nconss;
1242 
1243  /* add the constraint to the problem's constraint array */
1244  SCIP_CALL( probEnsureConssMem(prob, set, prob->nconss+1) );
1245  prob->conss[prob->nconss] = cons;
1246  prob->nconss++;
1247  prob->maxnconss = MAX(prob->maxnconss, prob->nconss);
1248 
1249  /* undelete constraint, if it was globally deleted in the past */
1250  cons->deleted = FALSE;
1251 
1252  /* mark constraint to be globally valid */
1253  SCIPconsSetLocal(cons, FALSE);
1254 
1255  /* capture constraint */
1256  SCIPconsCapture(cons);
1257 
1258  /* add constraint's name to the namespace */
1259  SCIP_CALL( SCIPprobAddConsName(prob, cons) );
1260 
1261  /* if the problem is the transformed problem, activate and lock constraint */
1262  if( prob->transformed )
1263  {
1264  /* activate constraint */
1265  if( !SCIPconsIsActive(cons) )
1266  {
1267  SCIP_CALL( SCIPconsActivate(cons, set, stat, -1, (stat->nnodes <= 1)) );
1268  }
1269 
1270  /* if constraint is a check-constraint, lock roundings of constraint's variables */
1271  if( SCIPconsIsChecked(cons) )
1272  {
1273  SCIP_CALL( SCIPconsAddLocks(cons, set, +1, 0) );
1274  }
1275  }
1276 
1277  return SCIP_OKAY;
1278 }
1279 
1280 /** releases and removes constraint from the problem; if the user has not captured the constraint for his own use, the
1281  * constraint may be invalid after the call
1282  */
1284  SCIP_PROB* prob, /**< problem data */
1285  BMS_BLKMEM* blkmem, /**< block memory */
1286  SCIP_SET* set, /**< global SCIP settings */
1287  SCIP_STAT* stat, /**< dynamic problem statistics */
1288  SCIP_CONS* cons /**< constraint to remove */
1289  )
1290 {
1291  int arraypos;
1292 
1293  assert(prob != NULL);
1294  assert(blkmem != NULL);
1295  assert(cons != NULL);
1296  assert(cons->addconssetchg == NULL);
1297  assert(0 <= cons->addarraypos && cons->addarraypos < prob->nconss);
1298  assert(prob->conss != NULL);
1299  assert(prob->conss[cons->addarraypos] == cons);
1300 
1301  /* if the problem is the transformed problem, deactivate and unlock constraint */
1302  if( prob->transformed )
1303  {
1304  /* if constraint is a check-constraint, unlock roundings of constraint's variables */
1305  if( SCIPconsIsChecked(cons) )
1306  {
1307  SCIP_CALL( SCIPconsAddLocks(cons, set, -1, 0) );
1308  }
1309 
1310  /* deactivate constraint, if it is currently active */
1311  if( cons->active && !cons->updatedeactivate )
1312  {
1313  SCIP_CALL( SCIPconsDeactivate(cons, set, stat) );
1314  }
1315  }
1316  assert(!cons->active || cons->updatedeactivate);
1317  assert(!cons->enabled || cons->updatedeactivate);
1318 
1319  /* remove constraint's name from the namespace */
1320  SCIP_CALL( SCIPprobRemoveConsName(prob, cons) );
1321 
1322  /* remove the constraint from the problem's constraint array */
1323  arraypos = cons->addarraypos;
1324  prob->conss[arraypos] = prob->conss[prob->nconss-1];
1325  assert(prob->conss[arraypos] != NULL);
1326  assert(prob->conss[arraypos]->addconssetchg == NULL);
1327  prob->conss[arraypos]->addarraypos = arraypos;
1328  prob->nconss--;
1329 
1330  /* mark the constraint to be no longer in the problem */
1331  cons->addarraypos = -1;
1332 
1333  /* release constraint */
1334  SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
1335 
1336  return SCIP_OKAY;
1337 }
1338 
1339 /** remembers the current number of constraints in the problem's internal data structure
1340  * - resets maximum number of constraints to current number of constraints
1341  * - remembers current number of constraints as starting number of constraints
1342  */
1344  SCIP_PROB* prob /**< problem data */
1345  )
1346 {
1347  assert(prob != NULL);
1348 
1349  /* remember number of constraints for statistic */
1350  prob->maxnconss = prob->nconss;
1351  prob->startnvars = prob->nvars;
1352  prob->startnconss = prob->nconss;
1353 }
1354 
1355 /** sets objective sense: minimization or maximization */
1357  SCIP_PROB* prob, /**< problem data */
1358  SCIP_OBJSENSE objsense /**< new objective sense */
1359  )
1360 {
1361  assert(prob != NULL);
1362  assert(prob->objsense == SCIP_OBJSENSE_MAXIMIZE || prob->objsense == SCIP_OBJSENSE_MINIMIZE);
1363  assert(objsense == SCIP_OBJSENSE_MAXIMIZE || objsense == SCIP_OBJSENSE_MINIMIZE);
1364 
1365  prob->objsense = objsense;
1366 }
1367 
1368 /** adds value to objective offset */
1370  SCIP_PROB* prob, /**< problem data */
1371  SCIP_Real addval /**< value to add to objective offset */
1372  )
1373 {
1374  assert(prob != NULL);
1375  assert(prob->transformed);
1376 
1377  SCIPdebugMessage("adding %g to objective offset %g: new offset = %g\n", addval, prob->objoffset, prob->objoffset + addval);
1378  prob->objoffset += addval;
1379 }
1380 
1381 /** sets the dual bound on objective function */
1383  SCIP_PROB* prob, /**< problem data */
1384  SCIP_Real dualbound /**< external dual bound */
1385  )
1386 {
1387  assert(prob != NULL);
1388 
1389  prob->dualbound = dualbound;
1390 }
1391 
1392 /** sets limit on objective function, such that only solutions better than this limit are accepted */
1394  SCIP_PROB* prob, /**< problem data */
1395  SCIP_Real objlim /**< external objective limit */
1396  )
1397 {
1398  assert(prob != NULL);
1399 
1400  prob->objlim = objlim;
1401 }
1402 
1403 /** informs the problem, that its objective value is always integral in every feasible solution */
1405  SCIP_PROB* prob /**< problem data */
1406  )
1407 {
1408  assert(prob != NULL);
1409 
1410  prob->objisintegral = TRUE;
1411 }
1412 
1413 /** sets integral objective value flag, if all variables with non-zero objective values are integral and have
1414  * integral objective value and also updates the cutoff bound if primal solution is already known
1415  */
1417  SCIP_PROB* transprob, /**< tranformed problem data */
1418  SCIP_PROB* origprob, /**< original problem data */
1419  BMS_BLKMEM* blkmem, /**< block memory */
1420  SCIP_SET* set, /**< global SCIP settings */
1421  SCIP_STAT* stat, /**< problem statistics data */
1422  SCIP_PRIMAL* primal, /**< primal data */
1423  SCIP_TREE* tree, /**< branch and bound tree */
1424  SCIP_LP* lp, /**< current LP data */
1425  SCIP_EVENTQUEUE* eventqueue /**< event queue */
1426  )
1427 {
1428  SCIP_Real obj;
1429  int v;
1430 
1431  assert(transprob != NULL);
1432  assert(origprob != NULL);
1433 
1434  /* if we know already, that the objective value is integral, nothing has to be done */
1435  if( transprob->objisintegral )
1436  return SCIP_OKAY;
1437 
1438  /* if there exist unknown variables, we cannot conclude that the objective value is always integral */
1439  if( set->nactivepricers != 0 )
1440  return SCIP_OKAY;
1441 
1442  /* if the objective value offset is fractional, the value itself is possibly fractional */
1443  if( !SCIPsetIsIntegral(set, transprob->objoffset) )
1444  return SCIP_OKAY;
1445 
1446  /* scan through the variables */
1447  for( v = 0; v < transprob->nvars; ++v )
1448  {
1449  /* get objective value of variable */
1450  obj = SCIPvarGetObj(transprob->vars[v]);
1451 
1452  /* check, if objective value is non-zero */
1453  if( !SCIPsetIsZero(set, obj) )
1454  {
1455  /* if variable's objective value is fractional, the problem's objective value may also be fractional */
1456  if( !SCIPsetIsIntegral(set, obj) )
1457  break;
1458 
1459  /* if variable with non-zero objective value is continuous, the problem's objective value may be fractional */
1460  if( SCIPvarGetType(transprob->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
1461  break;
1462  }
1463  }
1464 
1465  /* objective value is integral, if the variable loop scanned all variables */
1466  if( v == transprob->nvars )
1467  {
1468  transprob->objisintegral = TRUE;
1469 
1470  /* update upper bound and cutoff bound in primal data structure due to new internality information */
1471  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, lp) );
1472  }
1473 
1474  return SCIP_OKAY;
1475 }
1476 
1477 /** update the number of variables with non-zero objective coefficient */
1479  SCIP_PROB* prob, /**< problem data */
1480  SCIP_SET* set, /**< global SCIP settings */
1481  SCIP_Real oldobj, /**< old objective value for variable */
1482  SCIP_Real newobj /**< new objective value for variable */
1483  )
1484 {
1485  assert(prob->transformed);
1486 
1487  if( !SCIPsetIsZero(set, oldobj) )
1488  prob->nobjvars--;
1489 
1490  if( !SCIPsetIsZero(set, newobj) )
1491  prob->nobjvars++;
1492 }
1493 
1494 /** update the dual bound if its better as the current one */
1496  SCIP_PROB* prob, /**< problem data */
1497  SCIP_Real newbound /**< new dual bound for the node (if it's tighter than the old one) */
1498  )
1499 {
1500  if( prob->dualbound == SCIP_INVALID ) /*lint !e777*/
1501  SCIPprobSetDualbound(prob, newbound);
1502  else
1503  {
1504  switch( prob->objsense )
1505  {
1507  prob->dualbound = MAX(newbound, prob->dualbound);
1508  break;
1509 
1511  prob->dualbound = MIN(newbound, prob->dualbound);
1512  break;
1513 
1514  default:
1515  SCIPerrorMessage("invalid objective sense <%d>\n", prob->objsense);
1516  SCIPABORT();
1517  }
1518  }
1519 }
1520 
1521 /** if possible, scales objective function such that it is integral with gcd = 1 */
1523  SCIP_PROB* transprob, /**< tranformed problem data */
1524  SCIP_PROB* origprob, /**< original problem data */
1525  BMS_BLKMEM* blkmem, /**< block memory */
1526  SCIP_SET* set, /**< global SCIP settings */
1527  SCIP_STAT* stat, /**< problem statistics data */
1528  SCIP_PRIMAL* primal, /**< primal data */
1529  SCIP_TREE* tree, /**< branch and bound tree */
1530  SCIP_LP* lp, /**< current LP data */
1531  SCIP_EVENTQUEUE* eventqueue /**< event queue */
1532  )
1533 {
1534  int v;
1535  int nints;
1536 
1537  assert(transprob != NULL);
1538  assert(set != NULL);
1539 
1540  /* do not change objective if there are pricers involved */
1541  if( set->nactivepricers != 0 )
1542  return SCIP_OKAY;
1543 
1544  nints = transprob->nvars - transprob->ncontvars;
1545 
1546  /* scan through the continuous variables */
1547  for( v = nints; v < transprob->nvars; ++v )
1548  {
1549  SCIP_Real obj;
1550 
1551  /* get objective value of variable; it it is non-zero, no scaling can be applied */
1552  obj = SCIPvarGetObj(transprob->vars[v]);
1553  if( !SCIPsetIsZero(set, obj) )
1554  break;
1555  }
1556 
1557  /* only continue if all continuous variables have obj = 0 */
1558  if( v == transprob->nvars )
1559  {
1560  SCIP_Real* objvals;
1561  SCIP_Real intscalar;
1562  SCIP_Bool success;
1563 
1564  /* get temporary memory */
1565  SCIP_CALL( SCIPsetAllocBufferArray(set, &objvals, nints) );
1566 
1567  /* get objective values of integer variables */
1568  for( v = 0; v < nints; ++v )
1569  objvals[v] = SCIPvarGetObj(transprob->vars[v]);
1570 
1571  /* calculate integral scalar */
1573  &intscalar, &success) );
1574 
1575  SCIPdebugMessage("integral objective scalar: success=%u, intscalar=%g\n", success, intscalar);
1576 
1577  if( success )
1578  {
1579  SCIP_Longint gcd;
1580 
1581  assert(intscalar > 0.0);
1582 
1583  /* calculate gcd of resulting integral coefficients */
1584  gcd = 0;
1585  for( v = 0; v < nints && gcd != 1; ++v )
1586  {
1587  SCIP_Longint absobj;
1588 
1589  absobj = (SCIP_Longint)(REALABS(objvals[v]) * intscalar + 0.5);
1590  if( gcd == 0 )
1591  gcd = absobj;
1592  else if( absobj > 0 )
1593  gcd = SCIPcalcGreComDiv(gcd, absobj);
1594  }
1595  if( gcd != 0 )
1596  intscalar /= gcd;
1597  SCIPdebugMessage("integral objective scalar: gcd=%"SCIP_LONGINT_FORMAT", intscalar=%g\n", gcd, intscalar);
1598 
1599  /* only apply scaling if the final scalar is small enough */
1600  if( intscalar <= OBJSCALE_MAXFINALSCALE )
1601  {
1602  /* apply scaling */
1603  if( !SCIPsetIsEQ(set, intscalar, 1.0) )
1604  {
1605  /* calculate scaled objective values */
1606  for( v = 0; v < nints; ++v )
1607  {
1608  SCIP_Real newobj;
1609 
1610  /* check if new obj is really integral */
1611  newobj = intscalar * SCIPvarGetObj(transprob->vars[v]);
1612  if( !SCIPsetIsFeasIntegral(set, newobj) )
1613  break;
1614  objvals[v] = SCIPsetFeasFloor(set, newobj);
1615  }
1616 
1617  /* change the variables' objective values and adjust objscale and objoffset */
1618  if( v == nints )
1619  {
1620  for( v = 0; v < nints; ++v )
1621  {
1622  SCIPdebugMessage(" -> var <%s>: newobj = %.6f\n", SCIPvarGetName(transprob->vars[v]), objvals[v]);
1623  SCIP_CALL( SCIPvarChgObj(transprob->vars[v], blkmem, set, transprob, primal, lp, eventqueue, objvals[v]) );
1624  }
1625  transprob->objoffset *= intscalar;
1626  transprob->objscale /= intscalar;
1627  transprob->objisintegral = TRUE;
1628  SCIPdebugMessage("integral objective scalar: objscale=%g\n", transprob->objscale);
1629 
1630  /* update upperbound and cutoffbound in primal data structure */
1631  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, lp) );
1632  }
1633  }
1634  }
1635  }
1636 
1637  /* free temporary memory */
1638  SCIPsetFreeBufferArray(set, &objvals);
1639  }
1640 
1641  return SCIP_OKAY;
1642 }
1643 
1644 /** remembers the current solution as root solution in the problem variables */
1646  SCIP_PROB* prob, /**< problem data */
1647  SCIP_SET* set, /**< global SCIP settings */
1648  SCIP_LP* lp, /**< current LP data */
1649  SCIP_Bool roothaslp /**< is the root solution from LP? */
1650  )
1651 {
1652  int v;
1653 
1654  assert(prob != NULL);
1655  assert(prob->transformed);
1656 
1657  if( roothaslp )
1658  {
1659  for( v = 0; v < prob->nvars; ++v )
1660  SCIPvarStoreRootSol(prob->vars[v], roothaslp);
1661 
1663  SCIPlpStoreRootObjval(lp, set, prob);
1664  }
1665 }
1666 
1667 /** remembers the best solution w.r.t. root reduced cost propagation as root solution in the problem variables */
1669  SCIP_PROB* prob, /**< problem data */
1670  SCIP_SET* set, /**< global SCIP settings */
1671  SCIP_STAT* stat, /**< problem statistics */
1672  SCIP_LP* lp /**< current LP data */
1673  )
1674 {
1675  SCIP_Real rootlpobjval;
1676  int v;
1677 
1678  assert(prob != NULL);
1679  assert(lp != NULL);
1680  assert(prob->transformed);
1681  assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
1682 
1683  /* in case we have a zero objective fucntion, we skip the root reduced cost update */
1684  if( SCIPprobGetNObjVars(prob, set) == 0 )
1685  return;
1686 
1687  SCIPdebugMessage("update root reduced costs\n");
1688 
1689  /* compute current root LP objective value */
1690  rootlpobjval = SCIPlpGetObjval(lp, set, prob);
1691  assert(rootlpobjval != SCIP_INVALID); /*lint !e777*/
1692 
1693  for( v = 0; v < prob->nvars; ++v )
1694  {
1695  SCIP_VAR* var;
1696  SCIP_COL* col;
1697  SCIP_Real rootsol = 0.0;
1698  SCIP_Real rootredcost = 0.0;
1699 
1700  var = prob->vars[v];
1701  assert(var != NULL);
1702 
1703  /* check if the variable is part of the LP */
1705  continue;
1706 
1707  col = SCIPvarGetCol(var);
1708  assert(col != NULL);
1709 
1711 
1712  if( !SCIPvarIsBinary(var) )
1713  {
1714  rootsol = SCIPvarGetSol(var, TRUE);
1715  rootredcost = SCIPcolGetRedcost(col, stat, lp);
1716  }
1717  else
1718  {
1719  SCIP_Real primsol;
1720  SCIP_BASESTAT basestat;
1721  SCIP_Bool lpissolbasic;
1722 
1723  basestat = SCIPcolGetBasisStatus(col);
1724  lpissolbasic = SCIPlpIsSolBasic(lp);
1725  primsol = SCIPcolGetPrimsol(col);
1726 
1727  if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
1728  (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) ||
1729  SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
1730  {
1731  SCIP_Real lbrootredcost;
1732  SCIP_Real ubrootredcost;
1733 
1734  /* get reduced cost if the variable gets fixed to zero */
1735  lbrootredcost = SCIPvarGetImplRedcost(var, set, FALSE, stat, lp);
1736  assert( !SCIPsetIsFeasPositive(set, lbrootredcost)
1738 
1739  /* get reduced cost if the variable gets fixed to one */
1740  ubrootredcost = SCIPvarGetImplRedcost(var, set, TRUE, stat, lp);
1741  assert( !SCIPsetIsFeasNegative(set, ubrootredcost)
1743 
1744  if( -lbrootredcost > ubrootredcost )
1745  {
1746  rootredcost = lbrootredcost;
1747  rootsol = 1.0;
1748  }
1749  else
1750  {
1751  rootredcost = ubrootredcost;
1752  rootsol = 0.0;
1753  }
1754  }
1755  }
1756 
1757  /* update the current solution as best root solution in the problem variables if it is better */
1758  SCIPvarUpdateBestRootSol(var, set, rootsol, rootredcost, rootlpobjval);
1759  }
1760 }
1761 
1762 /** informs problem, that the presolving process was finished, and updates all internal data structures */
1764  SCIP_PROB* prob, /**< problem data */
1765  SCIP_SET* set /**< global SCIP settings */
1766  )
1767 { /*lint --e{715}*/
1768  return SCIP_OKAY;
1769 }
1770 
1771 /** initializes problem for branch and bound process and resets all constraint's ages and histories of current run */
1773  SCIP_PROB* prob, /**< problem data */
1774  SCIP_SET* set /**< global SCIP settings */
1775  )
1776 {
1777  int c;
1778  int v;
1779 
1780  assert(prob != NULL);
1781  assert(prob->transformed);
1782  assert(set != NULL);
1783 
1784  /* reset constraint's ages */
1785  for( c = 0; c < prob->nconss; ++c )
1786  {
1787  SCIP_CALL( SCIPconsResetAge(prob->conss[c], set) );
1788  }
1789 
1790  /* initialize variables for solving */
1791  for( v = 0; v < prob->nvars; ++v )
1792  SCIPvarInitSolve(prob->vars[v]);
1793 
1794  /* call user data function */
1795  if( prob->probinitsol != NULL )
1796  {
1797  SCIP_CALL( prob->probinitsol(set->scip, prob->probdata) );
1798  }
1799 
1800  /* assert that the counter for variables with nonzero objective is correct */
1801  assert(prob->nobjvars == SCIPprobGetNObjVars(prob, set));
1802 
1803  return SCIP_OKAY;
1804 }
1805 
1806 /** deinitializes problem after branch and bound process, and converts all COLUMN variables back into LOOSE variables */
1808  SCIP_PROB* prob, /**< problem data */
1809  BMS_BLKMEM* blkmem, /**< block memory */
1810  SCIP_SET* set, /**< global SCIP settings */
1811  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1812  SCIP_LP* lp, /**< current LP data */
1813  SCIP_Bool restart /**< was this exit solve call triggered by a restart? */
1814  )
1815 {
1816  SCIP_VAR* var;
1817  int v;
1818 
1819  assert(prob != NULL);
1820  assert(prob->transformed);
1821  assert(set != NULL);
1822 
1823  /* call user data function */
1824  if( prob->probexitsol != NULL )
1825  {
1826  SCIP_CALL( prob->probexitsol(set->scip, prob->probdata, restart) );
1827  }
1828 
1829  /* convert all COLUMN variables back into LOOSE variables */
1830  if( prob->ncolvars > 0 )
1831  {
1832  for( v = 0; v < prob->nvars; ++v )
1833  {
1834  var = prob->vars[v];
1836  {
1837  SCIP_CALL( SCIPvarLoose(var, blkmem, set, eventqueue, prob, lp) );
1838  }
1839 
1840  /* invalided root reduced cost, root reduced solution, and root LP objective value for each variable */
1841  SCIPvarSetBestRootSol(var, 0.0, 0.0, SCIP_INVALID);
1842  }
1843  }
1844  assert(prob->ncolvars == 0);
1845 
1846  return SCIP_OKAY;
1847 }
1848 
1849 
1850 
1851 
1852 /*
1853  * problem information
1854  */
1855 
1856 /** sets problem name */
1858  SCIP_PROB* prob, /**< problem data */
1859  const char* name /**< name to be set */
1860  )
1861 {
1862  assert(prob != NULL);
1863 
1864  BMSfreeMemoryArray(&(prob->name));
1865  SCIP_ALLOC( BMSduplicateMemoryArray(&(prob->name), name, strlen(name)+1) );
1866 
1867  return SCIP_OKAY;
1868 }
1869 
1870 /** returns the number of implicit binary variables, meaning variable of vartype != SCIP_VARTYPE_BINARY and !=
1871  * SCIP_VARTYPE_CONTINUOUS but with global bounds [0,1]
1872  *
1873  * @note this number needs to be computed, because it cannot be updated like the other counters for binary and integer
1874  * variables, each time the variable type changes(, we would need to update this counter each time a global bound
1875  * changes), even at the end of presolving this cannot be computed, because some variable can change to an
1876  * implicit binary status
1877  */
1879  SCIP_PROB* prob /**< problem data */
1880  )
1881 {
1882  int v;
1883  int nimplbinvars = 0;
1884 
1885  for( v = prob->nbinvars + prob->nintvars + prob->nimplvars - 1; v >= prob->nbinvars; --v )
1886  {
1887  if( SCIPvarIsBinary(prob->vars[v]) )
1888  ++nimplbinvars;
1889  }
1890 
1891  return nimplbinvars;
1892 }
1893 
1894 /** returns the number of variables with non-zero objective coefficient */
1896  SCIP_PROB* prob, /**< problem data */
1897  SCIP_SET* set /**< global SCIP settings */
1898  )
1899 {
1900  if( prob->transformed )
1901  {
1902  /* this is much too expensive, to check it in each debug run */
1903 #ifdef SCIP_MORE_DEBUG
1904  int nobjvars;
1905  int v;
1906 
1907  nobjvars = 0;
1908 
1909  for( v = prob->nvars - 1; v >= 0; --v )
1910  {
1911  if( !SCIPsetIsZero(set, SCIPvarGetObj(prob->vars[v])) )
1912  nobjvars++;
1913  }
1914 
1915  /* check that the internal count is correct */
1916  assert(prob->nobjvars == nobjvars);
1917 #endif
1918  return prob->nobjvars;
1919  }
1920  else
1921  {
1922  int nobjvars;
1923  int v;
1924 
1925  nobjvars = 0;
1926 
1927  for( v = prob->nvars - 1; v >= 0; --v )
1928  {
1929  if( !SCIPsetIsZero(set, SCIPvarGetObj(prob->vars[v])) )
1930  nobjvars++;
1931  }
1932  return nobjvars;
1933  }
1934 }
1935 
1936 /** returns the external value of the given internal objective value */
1938  SCIP_PROB* transprob, /**< tranformed problem data */
1939  SCIP_PROB* origprob, /**< original problem data */
1940  SCIP_SET* set, /**< global SCIP settings */
1941  SCIP_Real objval /**< internal objective value */
1942  )
1943 {
1944  assert(set != NULL);
1945  assert(origprob != NULL);
1946  assert(transprob != NULL);
1947  assert(transprob->transformed);
1948  assert(transprob->objscale > 0.0);
1949 
1950  if( SCIPsetIsInfinity(set, objval) )
1951  return (SCIP_Real)transprob->objsense * SCIPsetInfinity(set);
1952  else if( SCIPsetIsInfinity(set, -objval) )
1953  return -(SCIP_Real)transprob->objsense * SCIPsetInfinity(set);
1954  else
1955  return (SCIP_Real)transprob->objsense * transprob->objscale * (objval + transprob->objoffset) + origprob->objoffset;
1956 }
1957 
1958 /** returns the internal value of the given external objective value */
1960  SCIP_PROB* transprob, /**< tranformed problem data */
1961  SCIP_PROB* origprob, /**< original problem data */
1962  SCIP_SET* set, /**< global SCIP settings */
1963  SCIP_Real objval /**< external objective value */
1964  )
1965 {
1966  assert(set != NULL);
1967  assert(origprob != NULL);
1968  assert(transprob != NULL);
1969  assert(transprob->transformed);
1970  assert(transprob->objscale > 0.0);
1971 
1972  if( SCIPsetIsInfinity(set, objval) )
1973  return (SCIP_Real)transprob->objsense * SCIPsetInfinity(set);
1974  else if( SCIPsetIsInfinity(set, -objval) )
1975  return -(SCIP_Real)transprob->objsense * SCIPsetInfinity(set);
1976  else
1977  return (SCIP_Real)transprob->objsense * (objval - origprob->objoffset)/transprob->objscale - transprob->objoffset;
1978 }
1979 
1980 /** returns variable of the problem with given name */
1982  SCIP_PROB* prob, /**< problem data */
1983  const char* name /**< name of variable to find */
1984  )
1985 {
1986  assert(prob != NULL);
1987  assert(name != NULL);
1988 
1989  if( prob->varnames == NULL )
1990  {
1991  SCIPerrorMessage("Cannot find variable if variable-names hashtable was disabled (due to parameter <misc/usevartable>)\n");
1992  SCIPABORT();/*lint --e{527}*/ /* only in debug mode */
1993  return NULL;
1994  }
1995 
1996  return (SCIP_VAR*)(SCIPhashtableRetrieve(prob->varnames, (char*)name));
1997 }
1998 
1999 /** returns constraint of the problem with given name */
2001  SCIP_PROB* prob, /**< problem data */
2002  const char* name /**< name of variable to find */
2003  )
2004 {
2005  assert(prob != NULL);
2006  assert(name != NULL);
2007 
2008  if( prob->consnames == NULL )
2009  {
2010  SCIPerrorMessage("Cannot find constraint if constraint-names hashtable was disabled (due to parameter <misc/useconstable>)\n");
2011  SCIPABORT();/*lint --e{527}*/ /* only in debug mode */
2012  return NULL;
2013  }
2014 
2015  return (SCIP_CONS*)(SCIPhashtableRetrieve(prob->consnames, (char*)name));
2016 }
2017 
2018 /** displays current pseudo solution */
2020  SCIP_PROB* prob, /**< problem data */
2021  SCIP_SET* set, /**< global SCIP settings */
2022  SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
2023  )
2024 {
2025  SCIP_VAR* var;
2026  SCIP_Real solval;
2027  int v;
2028 
2029  for( v = 0; v < prob->nvars; ++v )
2030  {
2031  var = prob->vars[v];
2032  assert(var != NULL);
2033  solval = SCIPvarGetPseudoSol(var);
2034  if( !SCIPsetIsZero(set, solval) )
2035  SCIPmessagePrintInfo(messagehdlr, " <%s>=%.15g", SCIPvarGetName(var), solval);
2036  }
2037  SCIPmessagePrintInfo(messagehdlr, "\n");
2038 }
2039 
2040 /** outputs problem statistics */
2042  SCIP_PROB* prob, /**< problem data */
2043  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2044  FILE* file /**< output file (or NULL for standard output) */
2045  )
2046 {
2047  assert(prob != NULL);
2048 
2049  SCIPmessageFPrintInfo(messagehdlr, file, " Problem name : %s\n", prob->name);
2050  SCIPmessageFPrintInfo(messagehdlr, file, " Variables : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
2051  prob->nvars, prob->nbinvars, prob->nintvars, prob->nimplvars, prob->ncontvars);
2052  SCIPmessageFPrintInfo(messagehdlr, file, " Constraints : %d initial, %d maximal\n", prob->startnconss, prob->maxnconss);
2053  if( ! prob->transformed )
2054  SCIPmessageFPrintInfo(messagehdlr, file, " Objective sense : %s\n", prob->objsense == SCIP_OBJSENSE_MINIMIZE ? "minimize" : "maximize");
2055 }
2056 
2057 #ifndef NDEBUG
2058 
2059 /* In debug mode, the following methods are implemented as function calls to ensure
2060  * type validity.
2061  * In optimized mode, the methods are implemented as defines to improve performance.
2062  * However, we want to have them in the library anyways, so we have to undef the defines.
2063  */
2064 
2065 #undef SCIPprobIsTransformed
2066 #undef SCIPprobIsObjIntegral
2067 #undef SCIPprobAllColsInLP
2068 #undef SCIPprobGetObjlim
2069 #undef SCIPprobGetData
2070 #undef SCIPprobGetName
2071 #undef SCIPprobGetNVars
2072 #undef SCIPprobGetNBinVars
2073 #undef SCIPprobGetNIntVars
2074 #undef SCIPprobGetNImplVars
2075 #undef SCIPprobGetNContVars
2076 #undef SCIPprobGetVars
2077 #undef SCIPprobGetObjoffset
2078 
2079 /** is the problem data transformed */
2081  SCIP_PROB* prob /**< problem data */
2082  )
2083 {
2084  assert(prob != NULL);
2085 
2086  return prob->transformed;
2087 }
2088 
2089 /** returns whether the objective value is known to be integral in every feasible solution */
2091  SCIP_PROB* prob /**< problem data */
2092  )
2093 {
2094  assert(prob != NULL);
2095 
2096  return prob->objisintegral;
2097 }
2098 
2099 /** returns TRUE iff all columns, i.e. every variable with non-empty column w.r.t. all ever created rows, are present
2100  * in the LP, and FALSE, if there are additional already existing columns, that may be added to the LP in pricing
2101  */
2103  SCIP_PROB* prob, /**< problem data */
2104  SCIP_SET* set, /**< global SCIP settings */
2105  SCIP_LP* lp /**< current LP data */
2106  )
2107 {
2108  assert(SCIPlpGetNCols(lp) <= prob->ncolvars && prob->ncolvars <= prob->nvars);
2109 
2110  return (SCIPlpGetNCols(lp) == prob->ncolvars && set->nactivepricers == 0);
2111 }
2112 
2113 /** gets limit on objective function in external space */
2115  SCIP_PROB* prob, /**< problem data */
2116  SCIP_SET* set /**< global SCIP settings */
2117  )
2118 {
2119  assert(prob != NULL);
2120  assert(set != NULL);
2121 
2122  return prob->objlim >= SCIP_INVALID ? (SCIP_Real)(prob->objsense) * SCIPsetInfinity(set) : prob->objlim;
2123 }
2124 
2125 /** gets user problem data */
2127  SCIP_PROB* prob /**< problem */
2128  )
2129 {
2130  assert(prob != NULL);
2131 
2132  return prob->probdata;
2133 }
2134 
2135 /** gets problem name */
2136 const char* SCIPprobGetName(
2137  SCIP_PROB* prob /**< problem data */
2138  )
2139 {
2140  assert(prob != NULL);
2141  return prob->name;
2142 }
2143 
2144 /** gets number of problem variables */
2146  SCIP_PROB* prob /**< problem data */
2147  )
2148 {
2149  assert(prob != NULL);
2150  return prob->nvars;
2151 }
2152 
2153 /** gets number of binary problem variables */
2155  SCIP_PROB* prob /**< problem data */
2156  )
2157 {
2158  assert(prob != NULL);
2159  return prob->nbinvars;
2160 }
2161 
2162 /** gets number of integer problem variables */
2164  SCIP_PROB* prob /**< problem data */
2165  )
2166 {
2167  assert(prob != NULL);
2168  return prob->nintvars;
2169 }
2170 
2171 /** gets number of implicit integer problem variables */
2173  SCIP_PROB* prob /**< problem data */
2174  )
2175 {
2176  assert(prob != NULL);
2177  return prob->nimplvars;
2178 }
2179 
2180 /** gets number of continuous problem variables */
2182  SCIP_PROB* prob /**< problem data */
2183  )
2184 {
2185  assert(prob != NULL);
2186  return prob->ncontvars;
2187 }
2188 
2189 /** gets problem variables */
2191  SCIP_PROB* prob /**< problem data */
2192  )
2193 {
2194  assert(prob != NULL);
2195  return prob->vars;
2196 }
2197 
2198 /** gets the objective offset */
2200  SCIP_PROB* prob /**< problem data */
2201  )
2202 {
2203  assert(prob != NULL);
2204  return prob->objoffset;
2205 }
2206 
2207 /** gets the objective scalar */
2209  SCIP_PROB* prob /**< problem data */
2210  )
2211 {
2212  assert(prob != NULL);
2213  return prob->objscale;
2214 }
2215 
2216 #endif
2217