Scippy

SCIP

Solving Constraint Integer Programs

relax.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 relax.c
17  * @brief methods and datastructures for relaxation handlers
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  */
21 
22 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
23 
24 #include <assert.h>
25 #include <string.h>
26 
27 #include "scip/def.h"
28 #include "scip/set.h"
29 #include "scip/stat.h"
30 #include "scip/clock.h"
31 #include "scip/paramset.h"
32 #include "scip/scip.h"
33 #include "scip/relax.h"
34 #include "scip/pub_message.h"
35 #include "scip/pub_misc.h"
36 
37 #include "scip/struct_relax.h"
38 
39 
40 
41 /** compares two relaxation handlers w. r. to their priority */
42 SCIP_DECL_SORTPTRCOMP(SCIPrelaxComp)
43 { /*lint --e{715}*/
44  return ((SCIP_RELAX*)elem2)->priority - ((SCIP_RELAX*)elem1)->priority;
45 }
46 
47 /** comparison method for sorting relaxators w.r.t. to their name */
48 SCIP_DECL_SORTPTRCOMP(SCIPrelaxCompName)
49 {
50  return strcmp(SCIPrelaxGetName((SCIP_RELAX*)elem1), SCIPrelaxGetName((SCIP_RELAX*)elem2));
51 }
52 
53 /** method to call, when the priority of a relaxation handler was changed */
54 static
55 SCIP_DECL_PARAMCHGD(paramChgdRelaxPriority)
56 { /*lint --e{715}*/
57  SCIP_PARAMDATA* paramdata;
58 
59  paramdata = SCIPparamGetData(param);
60  assert(paramdata != NULL);
61 
62  /* use SCIPsetRelaxPriority() to mark the relaxs unsorted */
63  SCIP_CALL( SCIPsetRelaxPriority(scip, (SCIP_RELAX*)paramdata, SCIPparamGetInt(param)) ); /*lint !e740*/
64 
65  return SCIP_OKAY;
66 }
67 
68 /** copies the given relaxation handler to a new scip */
70  SCIP_RELAX* relax, /**< relaxation handler */
71  SCIP_SET* set /**< SCIP_SET of SCIP to copy to */
72  )
73 {
74  assert(relax != NULL);
75  assert(set != NULL);
76  assert(set->scip != NULL);
77 
78  if( relax->relaxcopy != NULL )
79  {
80  SCIPdebugMessage("including relaxation handler %s in subscip %p\n", SCIPrelaxGetName(relax), (void*)set->scip);
81  SCIP_CALL( relax->relaxcopy(set->scip, relax) );
82  }
83  return SCIP_OKAY;
84 }
85 
86 /** creates a relaxation handler */
88  SCIP_RELAX** relax, /**< pointer to relaxation handler data structure */
89  SCIP_SET* set, /**< global SCIP settings */
90  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
91  BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
92  const char* name, /**< name of relaxation handler */
93  const char* desc, /**< description of relaxation handler */
94  int priority, /**< priority of the relaxation handler (negative: after LP, non-negative: before LP) */
95  int freq, /**< frequency for calling relaxation handler */
96  SCIP_DECL_RELAXCOPY ((*relaxcopy)), /**< copy method of relaxation handler or NULL if you don't want to copy your plugin into sub-SCIPs */
97  SCIP_DECL_RELAXFREE ((*relaxfree)), /**< destructor of relaxation handler */
98  SCIP_DECL_RELAXINIT ((*relaxinit)), /**< initialize relaxation handler */
99  SCIP_DECL_RELAXEXIT ((*relaxexit)), /**< deinitialize relaxation handler */
100  SCIP_DECL_RELAXINITSOL((*relaxinitsol)), /**< solving process initialization method of relaxation handler */
101  SCIP_DECL_RELAXEXITSOL((*relaxexitsol)), /**< solving process deinitialization method of relaxation handler */
102  SCIP_DECL_RELAXEXEC ((*relaxexec)), /**< execution method of relaxation handler */
103  SCIP_RELAXDATA* relaxdata /**< relaxation handler data */
104  )
105 {
107  char paramdesc[SCIP_MAXSTRLEN];
108 
109  assert(relax != NULL);
110  assert(name != NULL);
111  assert(desc != NULL);
112  assert(freq >= -1);
113  assert(relaxexec != NULL);
114 
115  SCIP_ALLOC( BMSallocMemory(relax) );
116  SCIP_ALLOC( BMSduplicateMemoryArray(&(*relax)->name, name, strlen(name)+1) );
117  SCIP_ALLOC( BMSduplicateMemoryArray(&(*relax)->desc, desc, strlen(desc)+1) );
118  (*relax)->priority = priority;
119  (*relax)->freq = freq;
120  (*relax)->relaxcopy = relaxcopy;
121  (*relax)->relaxfree = relaxfree;
122  (*relax)->relaxinit = relaxinit;
123  (*relax)->relaxexit = relaxexit;
124  (*relax)->relaxinitsol = relaxinitsol;
125  (*relax)->relaxexitsol = relaxexitsol;
126  (*relax)->relaxexec = relaxexec;
127  (*relax)->relaxdata = relaxdata;
128  SCIP_CALL( SCIPclockCreate(&(*relax)->setuptime, SCIP_CLOCKTYPE_DEFAULT) );
129  SCIP_CALL( SCIPclockCreate(&(*relax)->relaxclock, SCIP_CLOCKTYPE_DEFAULT) );
130  (*relax)->ncalls = 0;
131  (*relax)->lastsolvednode = -1;
132  (*relax)->initialized = FALSE;
133 
134  /* add parameters */
135  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "relaxing/%s/priority", name);
136  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "priority of relaxation handler <%s>", name);
137  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
138  &(*relax)->priority, FALSE, priority, INT_MIN/4, INT_MAX/4,
139  paramChgdRelaxPriority, (SCIP_PARAMDATA*)(*relax)) ); /*lint !e740*/
140  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "relaxing/%s/freq", name);
141  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "frequency for calling relaxation handler <%s> (-1: never, 0: only in root node)", name);
142  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
143  &(*relax)->freq, FALSE, freq, -1, INT_MAX, NULL, NULL) );
144 
145  return SCIP_OKAY;
146 }
147 
148 /** calls destructor and frees memory of relaxation handler */
150  SCIP_RELAX** relax, /**< pointer to relaxation handler data structure */
151  SCIP_SET* set /**< global SCIP settings */
152  )
153 {
154  assert(relax != NULL);
155  assert(*relax != NULL);
156  assert(!(*relax)->initialized);
157  assert(set != NULL);
158 
159  /* call destructor of relaxation handler */
160  if( (*relax)->relaxfree != NULL )
161  {
162  SCIP_CALL( (*relax)->relaxfree(set->scip, *relax) );
163  }
164 
165  SCIPclockFree(&(*relax)->relaxclock);
166  SCIPclockFree(&(*relax)->setuptime);
167  BMSfreeMemoryArray(&(*relax)->name);
168  BMSfreeMemoryArray(&(*relax)->desc);
169  BMSfreeMemory(relax);
170 
171  return SCIP_OKAY;
172 }
173 
174 /** initializes relaxation handler */
176  SCIP_RELAX* relax, /**< relaxation handler */
177  SCIP_SET* set /**< global SCIP settings */
178  )
179 {
180  assert(relax != NULL);
181  assert(set != NULL);
182 
183  if( relax->initialized )
184  {
185  SCIPerrorMessage("relaxation handler <%s> already initialized\n", relax->name);
186  return SCIP_INVALIDCALL;
187  }
188 
189  if( set->misc_resetstat )
190  {
191  SCIPclockReset(relax->setuptime);
192  SCIPclockReset(relax->relaxclock);
193  relax->ncalls = 0;
194  relax->lastsolvednode = -1;
195  }
196 
197  if( relax->relaxinit != NULL )
198  {
199  /* start timing */
200  SCIPclockStart(relax->setuptime, set);
201 
202  SCIP_CALL( relax->relaxinit(set->scip, relax) );
203 
204  /* stop timing */
205  SCIPclockStop(relax->setuptime, set);
206  }
207  relax->initialized = TRUE;
208 
209  return SCIP_OKAY;
210 }
211 
212 /** calls exit method of relaxation handler */
214  SCIP_RELAX* relax, /**< relaxation handler */
215  SCIP_SET* set /**< global SCIP settings */
216  )
217 {
218  assert(relax != NULL);
219  assert(set != NULL);
220 
221  if( !relax->initialized )
222  {
223  SCIPerrorMessage("relaxation handler <%s> not initialized\n", relax->name);
224  return SCIP_INVALIDCALL;
225  }
226 
227  if( relax->relaxexit != NULL )
228  {
229  /* start timing */
230  SCIPclockStart(relax->setuptime, set);
231 
232  SCIP_CALL( relax->relaxexit(set->scip, relax) );
233 
234  /* stop timing */
235  SCIPclockStop(relax->setuptime, set);
236  }
237  relax->initialized = FALSE;
238 
239  return SCIP_OKAY;
240 }
241 
242 /** informs relaxation handler that the branch and bound process is being started */
244  SCIP_RELAX* relax, /**< relaxation handler */
245  SCIP_SET* set /**< global SCIP settings */
246  )
247 {
248  assert(relax != NULL);
249  assert(set != NULL);
250 
251  /* call solving process initialization method of relaxation handler */
252  if( relax->relaxinitsol != NULL )
253  {
254  /* start timing */
255  SCIPclockStart(relax->setuptime, set);
256 
257  SCIP_CALL( relax->relaxinitsol(set->scip, relax) );
258 
259  /* stop timing */
260  SCIPclockStop(relax->setuptime, set);
261  }
262 
263  return SCIP_OKAY;
264 }
265 
266 /** informs relaxation handler that the branch and bound process data is being freed */
268  SCIP_RELAX* relax, /**< relaxation handler */
269  SCIP_SET* set /**< global SCIP settings */
270  )
271 {
272  assert(relax != NULL);
273  assert(set != NULL);
274 
275  /* call solving process deinitialization method of relaxation handler */
276  if( relax->relaxexitsol != NULL )
277  {
278  /* start timing */
279  SCIPclockStart(relax->setuptime, set);
280 
281  SCIP_CALL( relax->relaxexitsol(set->scip, relax) );
282 
283  /* stop timing */
284  SCIPclockStop(relax->setuptime, set);
285  }
286 
287  return SCIP_OKAY;
288 }
289 
290 /** calls execution method of relaxation handler */
292  SCIP_RELAX* relax, /**< relaxation handler */
293  SCIP_SET* set, /**< global SCIP settings */
294  SCIP_STAT* stat, /**< dynamic problem statistics */
295  int depth, /**< depth of current node */
296  SCIP_Real* lowerbound, /**< pointer to lower bound computed by the relaxation handler */
297  SCIP_RESULT* result /**< pointer to store the result of the callback method */
298  )
299 {
300  assert(relax != NULL);
301  assert(relax->relaxexec != NULL);
302  assert(relax->freq >= -1);
303  assert(set != NULL);
304  assert(set->scip != NULL);
305  assert(depth >= 0);
306  assert(result != NULL);
307 
308  *result = SCIP_DIDNOTRUN;
309 
310  /* check, if the relaxation is already solved */
311  if( relax->lastsolvednode == stat->ntotalnodes )
312  return SCIP_OKAY;
313 
314  relax->lastsolvednode = stat->ntotalnodes;
315 
316  if( (depth == 0 && relax->freq == 0) || (relax->freq > 0 && depth % relax->freq == 0) )
317  {
318  SCIPdebugMessage("executing relaxation handler <%s>\n", relax->name);
319 
320  /* start timing */
321  SCIPclockStart(relax->relaxclock, set);
322 
323  /* call external relaxation method */
324  SCIP_CALL( relax->relaxexec(set->scip, relax, lowerbound, result) );
325 
326  /* stop timing */
327  SCIPclockStop(relax->relaxclock, set);
328 
329  /* evaluate result */
330  if( *result != SCIP_CUTOFF
331  && *result != SCIP_CONSADDED
332  && *result != SCIP_REDUCEDDOM
333  && *result != SCIP_SEPARATED
334  && *result != SCIP_SUCCESS
335  && *result != SCIP_SUSPENDED
336  && *result != SCIP_DIDNOTRUN )
337  {
338  SCIPerrorMessage("execution method of relaxation handler <%s> returned invalid result <%d>\n",
339  relax->name, *result);
340  return SCIP_INVALIDRESULT;
341  }
342  if( *result != SCIP_DIDNOTRUN )
343  {
344  relax->ncalls++;
345  if( *result == SCIP_SUSPENDED )
346  SCIPrelaxMarkUnsolved(relax);
347  }
348  }
349 
350  return SCIP_OKAY;
351 }
352 
353 /** gets user data of relaxation handler */
355  SCIP_RELAX* relax /**< relaxation handler */
356  )
357 {
358  assert(relax != NULL);
359 
360  return relax->relaxdata;
361 }
362 
363 /** sets user data of relaxation handler; user has to free old data in advance! */
365  SCIP_RELAX* relax, /**< relaxation handler */
366  SCIP_RELAXDATA* relaxdata /**< new relaxation handler user data */
367  )
368 {
369  assert(relax != NULL);
370 
371  relax->relaxdata = relaxdata;
372 }
373 
374 /** set copy method of relaxation handler */
376  SCIP_RELAX* relax, /**< relaxation handler */
377  SCIP_DECL_RELAXCOPY ((*relaxcopy)) /**< copy method of relaxation handler */
378  )
379 {
380  assert(relax != NULL);
381 
382  relax->relaxcopy = relaxcopy;
383 }
384 
385 /** set destructor of relaxation handler */
387  SCIP_RELAX* relax, /**< relaxation handler */
388  SCIP_DECL_RELAXFREE ((*relaxfree)) /**< destructor of relaxation handler */
389  )
390 {
391  assert(relax != NULL);
392 
393  relax->relaxfree = relaxfree;
394 }
395 
396 /** set initialization method of relaxation handler */
398  SCIP_RELAX* relax, /**< relaxation handler */
399  SCIP_DECL_RELAXINIT ((*relaxinit)) /**< initialize relaxation handler */
400  )
401 {
402  assert(relax != NULL);
403 
404  relax->relaxinit = relaxinit;
405 }
406 
407 /** set deinitialization method of relaxation handler */
409  SCIP_RELAX* relax, /**< relaxation handler */
410  SCIP_DECL_RELAXEXIT ((*relaxexit)) /**< deinitialize relaxation handler */
411  )
412 {
413  assert(relax != NULL);
414 
415  relax->relaxexit = relaxexit;
416 }
417 
418 /** set solving process initialization method of relaxation handler */
420  SCIP_RELAX* relax, /**< relaxation handler */
421  SCIP_DECL_RELAXINITSOL((*relaxinitsol)) /**< solving process initialization method of relaxation handler */
422  )
423 {
424  assert(relax != NULL);
425 
426  relax->relaxinitsol = relaxinitsol;
427 }
428 
429 /** set solving process deinitialization method of relaxation handler */
431  SCIP_RELAX* relax, /**< relaxation handler */
432  SCIP_DECL_RELAXEXITSOL((*relaxexitsol)) /**< solving process deinitialization relaxation handler */
433  )
434 {
435  assert(relax != NULL);
436 
437  relax->relaxexitsol = relaxexitsol;
438 }
439 
440 /** gets name of relaxation handler */
441 const char* SCIPrelaxGetName(
442  SCIP_RELAX* relax /**< relaxation handler */
443  )
444 {
445  assert(relax != NULL);
446 
447  return relax->name;
448 }
449 
450 /** gets description of relaxation handler */
451 const char* SCIPrelaxGetDesc(
452  SCIP_RELAX* relax /**< relaxation handler */
453  )
454 {
455  assert(relax != NULL);
456 
457  return relax->desc;
458 }
459 
460 /** gets priority of relaxation handler */
462  SCIP_RELAX* relax /**< relaxation handler */
463  )
464 {
465  assert(relax != NULL);
466 
467  return relax->priority;
468 }
469 
470 /** sets priority of relaxation handler */
472  SCIP_RELAX* relax, /**< relaxation handler */
473  SCIP_SET* set, /**< global SCIP settings */
474  int priority /**< new priority of the relaxation handler */
475  )
476 {
477  assert(relax != NULL);
478  assert(set != NULL);
479 
480  relax->priority = priority;
481  set->relaxssorted = FALSE;
482 }
483 
484 /** gets frequency of relaxation handler */
486  SCIP_RELAX* relax /**< relaxation handler */
487  )
488 {
489  assert(relax != NULL);
490 
491  return relax->freq;
492 }
493 
494 /** gets time in seconds used in this relaxator for setting up for next stages */
496  SCIP_RELAX* relax /**< relaxator */
497  )
498 {
499  assert(relax != NULL);
500 
501  return SCIPclockGetTime(relax->setuptime);
502 }
503 
504 /** gets time in seconds used in this relaxation handler */
506  SCIP_RELAX* relax /**< relaxation handler */
507  )
508 {
509  assert(relax != NULL);
510 
511  return SCIPclockGetTime(relax->relaxclock);
512 }
513 
514 /** gets the total number of times, the relaxation handler was called */
516  SCIP_RELAX* relax /**< relaxation handler */
517  )
518 {
519  assert(relax != NULL);
520 
521  return relax->ncalls;
522 }
523 
524 /** is relaxation handler initialized? */
526  SCIP_RELAX* relax /**< relaxation handler */
527  )
528 {
529  assert(relax != NULL);
530 
531  return relax->initialized;
532 }
533 
534 /** returns whether the relaxation was completely solved at the current node */
536  SCIP_RELAX* relax, /**< relaxation handler */
537  SCIP_STAT* stat /**< dynamic problem statistics */
538  )
539 {
540  assert(relax != NULL);
541  assert(stat != NULL);
542 
543  return (relax->lastsolvednode == stat->ntotalnodes);
544 }
545 
546 /** marks the current relaxation unsolved, s.t. the relaxation handler is called again in the next solving round */
548  SCIP_RELAX* relax /**< relaxation handler */
549  )
550 {
551  assert(relax != NULL);
552 
553  relax->lastsolvednode = -1;
554 }
555 
556 /*
557  * methods for the global relaxation data
558  */
559 
560 /** creates global relaxation data */
562  SCIP_RELAXATION** relaxation /**< global relaxation data */
563  )
564 {
565  assert(relaxation != NULL);
566  SCIP_ALLOC( BMSallocMemory(relaxation) );
567  (*relaxation)->relaxsolobjval = 0.0;
568  (*relaxation)->relaxsolvalid = FALSE;
569  (*relaxation)->relaxsolzero = TRUE;
570 
571  return SCIP_OKAY;
572 }
573 
574 /** frees global relaxation data */
576  SCIP_RELAXATION** relaxation /**< global relaxation data */
577  )
578 {
579  assert(relaxation != NULL);
580 
581  BMSfreeMemory(relaxation);
582 
583  return SCIP_OKAY;
584 }
585 
586 /** sets the relaxsolzero flag in the relaxation data to the given value */
588  SCIP_RELAXATION* relaxation, /**< global relaxation data */
589  SCIP_Bool iszero /**< are all values of the relaxation solution set to zero? */
590  )
591 {
592  assert(relaxation != NULL);
593 
594  relaxation->relaxsolzero = iszero;
595 }
596 
597 /** returns whether the global relaxation solution is cleared and all values are set to zero */
599  SCIP_RELAXATION* relaxation /**< global relaxation data */
600  )
601 {
602  assert(relaxation != NULL);
603 
604  return relaxation->relaxsolzero;
605 }
606 
607 /** sets the relaxsolvalid flag in the relaxation data to the given value */
609  SCIP_RELAXATION* relaxation, /**< global relaxation data */
610  SCIP_Bool isvalid /**< is the stored solution valid? */
611  )
612 {
613  assert(relaxation != NULL);
614 
615  relaxation->relaxsolvalid = isvalid;
616 }
617 
618 /** returns whether the global relaxation solution is valid */
620  SCIP_RELAXATION* relaxation /**< global relaxation data */
621  )
622 {
623  assert(relaxation != NULL);
624 
625  return relaxation->relaxsolvalid;
626 }
627 
628 /** sets the objective value of the global relaxation solution */
630  SCIP_RELAXATION* relaxation, /**< global relaxation data */
631  SCIP_Real obj /**< objective value */
632  )
633 {
634  assert(relaxation != NULL);
635 
636  relaxation->relaxsolobjval = obj;
637 }
638 
639 /** returns the objective value of the global relaxation solution w.r.t. the transformed problem */
641  SCIP_RELAXATION* relaxation /**< global relaxation data */
642  )
643 {
644  assert(relaxation != NULL);
645 
646  return relaxation->relaxsolobjval;
647 }
648 
649 /** adds the given value to the global relaxation solution's objective value */
651  SCIP_RELAXATION* relaxation, /**< global relaxation data */
652  SCIP_Real val /**< value to add to the objective value */
653  )
654 {
655  assert(relaxation != NULL);
656 
657  relaxation->relaxsolobjval += val;
658 }
659