Scippy

SCIP

Solving Constraint Integer Programs

sepa.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 sepa.c
17  * @brief methods and datastructures for separators
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/sepastore.h"
33 #include "scip/scip.h"
34 #include "scip/sepa.h"
35 #include "scip/pub_message.h"
36 #include "scip/pub_misc.h"
37 
38 #include "scip/struct_sepa.h"
39 
40 
41 
42 /** compares two separators w. r. to their priority */
43 SCIP_DECL_SORTPTRCOMP(SCIPsepaComp)
44 { /*lint --e{715}*/
45  return ((SCIP_SEPA*)elem2)->priority - ((SCIP_SEPA*)elem1)->priority;
46 }
47 
48 /** comparison method for sorting separators w.r.t. to their name */
49 SCIP_DECL_SORTPTRCOMP(SCIPsepaCompName)
50 {
51  return strcmp(SCIPsepaGetName((SCIP_SEPA*)elem1), SCIPsepaGetName((SCIP_SEPA*)elem2));
52 }
53 
54 /** method to call, when the priority of a separator was changed */
55 static
56 SCIP_DECL_PARAMCHGD(paramChgdSepaPriority)
57 { /*lint --e{715}*/
58  SCIP_PARAMDATA* paramdata;
59 
60  paramdata = SCIPparamGetData(param);
61  assert(paramdata != NULL);
62 
63  /* use SCIPsetSepaPriority() to mark the sepas unsorted */
64  SCIP_CALL( SCIPsetSepaPriority(scip, (SCIP_SEPA*)paramdata, SCIPparamGetInt(param)) ); /*lint !e740*/
65 
66  return SCIP_OKAY;
67 }
68 
69 /** copies the given separator to a new scip */
71  SCIP_SEPA* sepa, /**< separator */
72  SCIP_SET* set /**< SCIP_SET of SCIP to copy to */
73  )
74 {
75  assert(sepa != NULL);
76  assert(set != NULL);
77  assert(set->scip != NULL);
78 
79  if( sepa->sepacopy != NULL )
80  {
81  SCIPdebugMessage("including separator %s in subscip %p\n", SCIPsepaGetName(sepa), (void*)set->scip);
82  SCIP_CALL( sepa->sepacopy(set->scip, sepa) );
83  }
84  return SCIP_OKAY;
85 }
86 
87 /** creates a separator */
89  SCIP_SEPA** sepa, /**< pointer to separator data structure */
90  SCIP_SET* set, /**< global SCIP settings */
91  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
92  BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
93  const char* name, /**< name of separator */
94  const char* desc, /**< description of separator */
95  int priority, /**< priority of separator (>= 0: before, < 0: after constraint handlers) */
96  int freq, /**< frequency for calling separator */
97  SCIP_Real maxbounddist, /**< maximal relative distance from current node's dual bound to primal bound compared
98  * to best node's dual bound for applying separation */
99  SCIP_Bool usessubscip, /**< does the separator use a secondary SCIP instance? */
100  SCIP_Bool delay, /**< should separator be delayed, if other separators found cuts? */
101  SCIP_DECL_SEPACOPY ((*sepacopy)), /**< copy method of separator or NULL if you don't want to copy your plugin into sub-SCIPs */
102  SCIP_DECL_SEPAFREE ((*sepafree)), /**< destructor of separator */
103  SCIP_DECL_SEPAINIT ((*sepainit)), /**< initialize separator */
104  SCIP_DECL_SEPAEXIT ((*sepaexit)), /**< deinitialize separator */
105  SCIP_DECL_SEPAINITSOL ((*sepainitsol)), /**< solving process initialization method of separator */
106  SCIP_DECL_SEPAEXITSOL ((*sepaexitsol)), /**< solving process deinitialization method of separator */
107  SCIP_DECL_SEPAEXECLP ((*sepaexeclp)), /**< LP solution separation method of separator */
108  SCIP_DECL_SEPAEXECSOL ((*sepaexecsol)), /**< arbitrary primal solution separation method of separator */
109  SCIP_SEPADATA* sepadata /**< separator data */
110  )
111 {
113  char paramdesc[SCIP_MAXSTRLEN];
114 
115  assert(sepa != NULL);
116  assert(name != NULL);
117  assert(desc != NULL);
118  assert(freq >= -1);
119  assert(0.0 <= maxbounddist && maxbounddist <= 1.0);
120  assert(sepaexeclp != NULL || sepaexecsol != NULL);
121 
122  SCIP_ALLOC( BMSallocMemory(sepa) );
123  SCIP_ALLOC( BMSduplicateMemoryArray(&(*sepa)->name, name, strlen(name)+1) );
124  SCIP_ALLOC( BMSduplicateMemoryArray(&(*sepa)->desc, desc, strlen(desc)+1) );
125  (*sepa)->priority = priority;
126  (*sepa)->freq = freq;
127  (*sepa)->maxbounddist = maxbounddist;
128  (*sepa)->usessubscip = usessubscip;
129  (*sepa)->sepacopy = sepacopy;
130  (*sepa)->sepafree = sepafree;
131  (*sepa)->sepainit = sepainit;
132  (*sepa)->sepaexit = sepaexit;
133  (*sepa)->sepainitsol = sepainitsol;
134  (*sepa)->sepaexitsol = sepaexitsol;
135  (*sepa)->sepaexeclp = sepaexeclp;
136  (*sepa)->sepaexecsol = sepaexecsol;
137  (*sepa)->sepadata = sepadata;
138  SCIP_CALL( SCIPclockCreate(&(*sepa)->setuptime, SCIP_CLOCKTYPE_DEFAULT) );
139  SCIP_CALL( SCIPclockCreate(&(*sepa)->sepaclock, SCIP_CLOCKTYPE_DEFAULT) );
140  (*sepa)->lastsepanode = -1;
141  (*sepa)->ncalls = 0;
142  (*sepa)->ncutoffs = 0;
143  (*sepa)->ncutsfound = 0;
144  (*sepa)->ncutsapplied = 0;
145  (*sepa)->nconssfound = 0;
146  (*sepa)->ndomredsfound = 0;
147  (*sepa)->ncallsatnode = 0;
148  (*sepa)->ncutsfoundatnode = 0;
149  (*sepa)->lpwasdelayed = FALSE;
150  (*sepa)->solwasdelayed = FALSE;
151  (*sepa)->initialized = FALSE;
152 
153  /* add parameters */
154  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "separating/%s/priority", name);
155  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "priority of separator <%s>", name);
156  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
157  &(*sepa)->priority, TRUE, priority, INT_MIN/4, INT_MAX/4,
158  paramChgdSepaPriority, (SCIP_PARAMDATA*)(*sepa)) ); /*lint !e740*/
159 
160  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "separating/%s/freq", name);
161  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "frequency for calling separator <%s> (-1: never, 0: only in root node)", name);
162  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
163  &(*sepa)->freq, FALSE, freq, -1, INT_MAX, NULL, NULL) );
164 
165  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "separating/%s/maxbounddist", name);
166  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for applying separator <%s> (0.0: only on current best node, 1.0: on all nodes)",
167  name);
168  SCIP_CALL( SCIPsetAddRealParam(set, messagehdlr, blkmem, paramname, paramdesc,
169  &(*sepa)->maxbounddist, TRUE, maxbounddist, 0.0, 1.0, NULL, NULL) );
170 
171  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "separating/%s/delay", name);
172  SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
173  "should separator be delayed, if other separators found cuts?",
174  &(*sepa)->delay, TRUE, delay, NULL, NULL) ); /*lint !e740*/
175 
176  return SCIP_OKAY;
177 }
178 
179 /** calls destructor and frees memory of separator */
181  SCIP_SEPA** sepa, /**< pointer to separator data structure */
182  SCIP_SET* set /**< global SCIP settings */
183  )
184 {
185  assert(sepa != NULL);
186  assert(*sepa != NULL);
187  assert(!(*sepa)->initialized);
188  assert(set != NULL);
189 
190  /* call destructor of separator */
191  if( (*sepa)->sepafree != NULL )
192  {
193  SCIP_CALL( (*sepa)->sepafree(set->scip, *sepa) );
194  }
195 
196  SCIPclockFree(&(*sepa)->sepaclock);
197  SCIPclockFree(&(*sepa)->setuptime);
198  BMSfreeMemoryArray(&(*sepa)->name);
199  BMSfreeMemoryArray(&(*sepa)->desc);
200  BMSfreeMemory(sepa);
201 
202  return SCIP_OKAY;
203 }
204 
205 /** initializes separator */
207  SCIP_SEPA* sepa, /**< separator */
208  SCIP_SET* set /**< global SCIP settings */
209  )
210 {
211  assert(sepa != NULL);
212  assert(set != NULL);
213 
214  if( sepa->initialized )
215  {
216  SCIPerrorMessage("separator <%s> already initialized\n", sepa->name);
217  return SCIP_INVALIDCALL;
218  }
219 
220  if( set->misc_resetstat )
221  {
222  SCIPclockReset(sepa->setuptime);
223  SCIPclockReset(sepa->sepaclock);
224 
225  sepa->lastsepanode = -1;
226  sepa->ncalls = 0;
227  sepa->ncutoffs = 0;
228  sepa->ncutsfound = 0;
229  sepa->ncutsapplied = 0;
230  sepa->nconssfound = 0;
231  sepa->ndomredsfound = 0;
232  sepa->ncallsatnode = 0;
233  sepa->ncutsfoundatnode = 0;
234  sepa->lpwasdelayed = FALSE;
235  sepa->solwasdelayed = FALSE;
236  }
237 
238  if( sepa->sepainit != NULL )
239  {
240  /* start timing */
241  SCIPclockStart(sepa->setuptime, set);
242 
243  SCIP_CALL( sepa->sepainit(set->scip, sepa) );
244 
245  /* stop timing */
246  SCIPclockStop(sepa->setuptime, set);
247  }
248  sepa->initialized = TRUE;
249 
250  return SCIP_OKAY;
251 }
252 
253 /** calls exit method of separator */
255  SCIP_SEPA* sepa, /**< separator */
256  SCIP_SET* set /**< global SCIP settings */
257  )
258 {
259  assert(sepa != NULL);
260  assert(set != NULL);
261 
262  if( !sepa->initialized )
263  {
264  SCIPerrorMessage("separator <%s> not initialized\n", sepa->name);
265  return SCIP_INVALIDCALL;
266  }
267 
268  if( sepa->sepaexit != NULL )
269  {
270  /* start timing */
271  SCIPclockStart(sepa->setuptime, set);
272 
273  SCIP_CALL( sepa->sepaexit(set->scip, sepa) );
274 
275  /* stop timing */
276  SCIPclockStop(sepa->setuptime, set);
277  }
278  sepa->initialized = FALSE;
279 
280  return SCIP_OKAY;
281 }
282 
283 /** informs separator that the branch and bound process is being started */
285  SCIP_SEPA* sepa, /**< separator */
286  SCIP_SET* set /**< global SCIP settings */
287  )
288 {
289  assert(sepa != NULL);
290  assert(set != NULL);
291 
292  sepa->lpwasdelayed = FALSE;
293  sepa->solwasdelayed = FALSE;
294 
295  /* call solving process initialization method of separator */
296  if( sepa->sepainitsol != NULL )
297  {
298  /* start timing */
299  SCIPclockStart(sepa->setuptime, set);
300 
301  SCIP_CALL( sepa->sepainitsol(set->scip, sepa) );
302 
303  /* stop timing */
304  SCIPclockStop(sepa->setuptime, set);
305  }
306 
307  return SCIP_OKAY;
308 }
309 
310 /** informs separator that the branch and bound process data is being freed */
312  SCIP_SEPA* sepa, /**< separator */
313  SCIP_SET* set /**< global SCIP settings */
314  )
315 {
316  assert(sepa != NULL);
317  assert(set != NULL);
318 
319  /* call solving process deinitialization method of separator */
320  if( sepa->sepaexitsol != NULL )
321  {
322  /* start timing */
323  SCIPclockStart(sepa->setuptime, set);
324 
325  SCIP_CALL( sepa->sepaexitsol(set->scip, sepa) );
326 
327  /* stop timing */
328  SCIPclockStop(sepa->setuptime, set);
329  }
330 
331  return SCIP_OKAY;
332 }
333 
334 /** calls LP separation method of separator */
336  SCIP_SEPA* sepa, /**< separator */
337  SCIP_SET* set, /**< global SCIP settings */
338  SCIP_STAT* stat, /**< dynamic problem statistics */
339  SCIP_SEPASTORE* sepastore, /**< separation storage */
340  int depth, /**< depth of current node */
341  SCIP_Real bounddist, /**< current relative distance of local dual bound to global dual bound */
342  SCIP_Bool execdelayed, /**< execute separator even if it is marked to be delayed */
343  SCIP_RESULT* result /**< pointer to store the result of the callback method */
344  )
345 {
346  assert(sepa != NULL);
347  assert(sepa->freq >= -1);
348  assert(0.0 <= sepa->maxbounddist && sepa->maxbounddist <= 1.0);
349  assert(0.0 <= bounddist && bounddist <= 1.0);
350  assert(set != NULL);
351  assert(set->scip != NULL);
352  assert(stat != NULL);
353  assert(depth >= 0);
354  assert(result != NULL);
355 
356  if( sepa->sepaexeclp != NULL
357  && SCIPsetIsLE(set, bounddist, sepa->maxbounddist)
358  && ((depth == 0 && sepa->freq == 0) || (sepa->freq > 0 && depth % sepa->freq == 0) || sepa->lpwasdelayed) )
359  {
360  if( (!sepa->delay && !sepa->lpwasdelayed) || execdelayed )
361  {
362  SCIP_Longint oldndomchgs;
363  SCIP_Longint oldnprobdomchgs;
364  int oldncuts;
365  int oldnactiveconss;
366  int ncutsfound;
367 
368  SCIPdebugMessage("executing separator <%s> on LP solution\n", sepa->name);
369 
370  oldndomchgs = stat->nboundchgs + stat->nholechgs;
371  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
372  oldncuts = SCIPsepastoreGetNCuts(sepastore);
373  oldnactiveconss = stat->nactiveconss;
374 
375  /* reset the statistics for current node */
376  if( sepa->lastsepanode != stat->ntotalnodes )
377  {
378  sepa->ncallsatnode = 0;
379  sepa->ncutsfoundatnode = 0;
380  }
381 
382  /* start timing */
383  SCIPclockStart(sepa->sepaclock, set);
384 
385  /* call external separation method */
386  SCIP_CALL( sepa->sepaexeclp(set->scip, sepa, result) );
387 
388  /* stop timing */
389  SCIPclockStop(sepa->sepaclock, set);
390 
391  /* update statistics */
392  if( *result != SCIP_DIDNOTRUN && *result != SCIP_DELAYED )
393  {
394  sepa->ncalls++;
395  sepa->ncallsatnode++;
396  sepa->lastsepanode = stat->ntotalnodes;
397  }
398  if( *result == SCIP_CUTOFF )
399  sepa->ncutoffs++;
400  ncutsfound = SCIPsepastoreGetNCuts(sepastore) - oldncuts;
401  sepa->ncutsfound += ncutsfound;
402  sepa->ncutsfoundatnode += ncutsfound;
403  sepa->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/
404 
405  /* update domain reductions; therefore remove the domain
406  * reduction counts which were generated in probing mode */
407  sepa->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
408  sepa->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
409 
410  /* evaluate result */
411  if( *result != SCIP_CUTOFF
412  && *result != SCIP_CONSADDED
413  && *result != SCIP_REDUCEDDOM
414  && *result != SCIP_SEPARATED
415  && *result != SCIP_NEWROUND
416  && *result != SCIP_DIDNOTFIND
417  && *result != SCIP_DIDNOTRUN
418  && *result != SCIP_DELAYED )
419  {
420  SCIPerrorMessage("execution method of separator <%s> returned invalid result <%d>\n",
421  sepa->name, *result);
422  return SCIP_INVALIDRESULT;
423  }
424  }
425  else
426  {
427  SCIPdebugMessage("separator <%s> was delayed\n", sepa->name);
428  *result = SCIP_DELAYED;
429  }
430 
431  /* remember whether separator was delayed */
432  sepa->lpwasdelayed = (*result == SCIP_DELAYED);
433  }
434  else
435  *result = SCIP_DIDNOTRUN;
436 
437  return SCIP_OKAY;
438 }
439 
440 /** calls primal solution separation method of separator */
442  SCIP_SEPA* sepa, /**< separator */
443  SCIP_SET* set, /**< global SCIP settings */
444  SCIP_STAT* stat, /**< dynamic problem statistics */
445  SCIP_SEPASTORE* sepastore, /**< separation storage */
446  SCIP_SOL* sol, /**< primal solution that should be separated */
447  int depth, /**< depth of current node */
448  SCIP_Bool execdelayed, /**< execute separator even if it is marked to be delayed */
449  SCIP_RESULT* result /**< pointer to store the result of the callback method */
450  )
451 {
452  assert(sepa != NULL);
453  assert(sepa->freq >= -1);
454  assert(set != NULL);
455  assert(set->scip != NULL);
456  assert(stat != NULL);
457  assert(depth >= 0);
458  assert(result != NULL);
459 
460  if( sepa->sepaexecsol != NULL
461  && ((depth == 0 && sepa->freq == 0) || (sepa->freq > 0 && depth % sepa->freq == 0) || sepa->solwasdelayed) )
462  {
463  if( (!sepa->delay && !sepa->solwasdelayed) || execdelayed )
464  {
465  SCIP_Longint oldndomchgs;
466  SCIP_Longint oldnprobdomchgs;
467  int oldncuts;
468  int oldnactiveconss;
469  int ncutsfound;
470 
471  SCIPdebugMessage("executing separator <%s> on solution %p\n", sepa->name, (void*)sol);
472 
473  oldndomchgs = stat->nboundchgs + stat->nholechgs;
474  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
475  oldncuts = SCIPsepastoreGetNCuts(sepastore);
476  oldnactiveconss = stat->nactiveconss;
477 
478  /* reset the statistics for current node */
479  if( sepa->lastsepanode != stat->ntotalnodes )
480  {
481  sepa->ncallsatnode = 0;
482  sepa->ncutsfoundatnode = 0;
483  }
484 
485  /* start timing */
486  SCIPclockStart(sepa->sepaclock, set);
487 
488  /* call external separation method */
489  SCIP_CALL( sepa->sepaexecsol(set->scip, sepa, sol, result) );
490 
491  /* stop timing */
492  SCIPclockStop(sepa->sepaclock, set);
493 
494  /* update statistics */
495  if( *result != SCIP_DIDNOTRUN && *result != SCIP_DELAYED )
496  {
497  sepa->ncalls++;
498  sepa->ncallsatnode++;
499  sepa->lastsepanode = stat->ntotalnodes;
500  }
501  if( *result == SCIP_CUTOFF )
502  sepa->ncutoffs++;
503  ncutsfound = SCIPsepastoreGetNCuts(sepastore) - oldncuts;
504  sepa->ncutsfound += ncutsfound;
505  sepa->ncutsfoundatnode += ncutsfound;
506  sepa->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/
507 
508  /* update domain reductions; therefore remove the domain
509  * reduction counts which were generated in probing mode */
510  sepa->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
511  sepa->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
512 
513  /* evaluate result */
514  if( *result != SCIP_CUTOFF
515  && *result != SCIP_CONSADDED
516  && *result != SCIP_REDUCEDDOM
517  && *result != SCIP_SEPARATED
518  && *result != SCIP_NEWROUND
519  && *result != SCIP_DIDNOTFIND
520  && *result != SCIP_DIDNOTRUN
521  && *result != SCIP_DELAYED )
522  {
523  SCIPerrorMessage("execution method of separator <%s> returned invalid result <%d>\n",
524  sepa->name, *result);
525  return SCIP_INVALIDRESULT;
526  }
527  }
528  else
529  {
530  SCIPdebugMessage("separator <%s> was delayed\n", sepa->name);
531  *result = SCIP_DELAYED;
532  }
533 
534  /* remember whether separator was delayed */
535  sepa->solwasdelayed = (*result == SCIP_DELAYED);
536  }
537  else
538  *result = SCIP_DIDNOTRUN;
539 
540  return SCIP_OKAY;
541 }
542 
543 /** gets user data of separator */
545  SCIP_SEPA* sepa /**< separator */
546  )
547 {
548  assert(sepa != NULL);
549 
550  return sepa->sepadata;
551 }
552 
553 /** sets user data of separator; user has to free old data in advance! */
555  SCIP_SEPA* sepa, /**< separator */
556  SCIP_SEPADATA* sepadata /**< new separator user data */
557  )
558 {
559  assert(sepa != NULL);
560 
561  sepa->sepadata = sepadata;
562 }
563 
564 /* new callback/method setter methods */
565 
566 /** sets copy method of separator */
568  SCIP_SEPA* sepa, /**< separator */
569  SCIP_DECL_SEPACOPY ((*sepacopy)) /**< copy method of separator or NULL if you don't want to copy your plugin into sub-SCIPs */
570  )
571 {
572  assert(sepa != NULL);
573 
574  sepa->sepacopy = sepacopy;
575 }
576 
577 /** sets destructor method of separator */
579  SCIP_SEPA* sepa, /**< separator */
580  SCIP_DECL_SEPAFREE ((*sepafree)) /**< destructor of separator */
581  )
582 {
583  assert(sepa != NULL);
584 
585  sepa->sepafree = sepafree;
586 }
587 
588 /** sets initialization method of separator */
590  SCIP_SEPA* sepa, /**< separator */
591  SCIP_DECL_SEPAINIT ((*sepainit)) /**< initialize separator */
592  )
593 {
594  assert(sepa != NULL);
595 
596  sepa->sepainit = sepainit;
597 }
598 
599 /** sets deinitialization method of separator */
601  SCIP_SEPA* sepa, /**< separator */
602  SCIP_DECL_SEPAEXIT ((*sepaexit)) /**< deinitialize separator */
603  )
604 {
605  assert(sepa != NULL);
606 
607  sepa->sepaexit = sepaexit;
608 }
609 
610 /** sets solving process initialization method of separator */
612  SCIP_SEPA* sepa, /**< separator */
613  SCIP_DECL_SEPAINITSOL ((*sepainitsol)) /**< solving process initialization method of separator */
614  )
615 {
616  assert(sepa != NULL);
617 
618  sepa->sepainitsol = sepainitsol;
619 }
620 
621 /** sets solving process deinitialization method of separator */
623  SCIP_SEPA* sepa, /**< separator */
624  SCIP_DECL_SEPAEXITSOL ((*sepaexitsol)) /**< solving process deinitialization method of separator */
625  )
626 {
627  assert(sepa != NULL);
628 
629  sepa->sepaexitsol = sepaexitsol;
630 }
631 
632 /** gets name of separator */
633 const char* SCIPsepaGetName(
634  SCIP_SEPA* sepa /**< separator */
635  )
636 {
637  assert(sepa != NULL);
638 
639  return sepa->name;
640 }
641 
642 /** gets description of separator */
643 const char* SCIPsepaGetDesc(
644  SCIP_SEPA* sepa /**< separator */
645  )
646 {
647  assert(sepa != NULL);
648 
649  return sepa->desc;
650 }
651 
652 /** gets priority of separator */
654  SCIP_SEPA* sepa /**< separator */
655  )
656 {
657  assert(sepa != NULL);
658 
659  return sepa->priority;
660 }
661 
662 /** sets priority of separator */
664  SCIP_SEPA* sepa, /**< separator */
665  SCIP_SET* set, /**< global SCIP settings */
666  int priority /**< new priority of the separator */
667  )
668 {
669  assert(sepa != NULL);
670  assert(set != NULL);
671 
672  sepa->priority = priority;
673  set->sepassorted = FALSE;
674 }
675 
676 /** gets frequency of separator */
678  SCIP_SEPA* sepa /**< separator */
679  )
680 {
681  assert(sepa != NULL);
682 
683  return sepa->freq;
684 }
685 
686 /** sets frequency of separator */
688  SCIP_SEPA* sepa, /**< separator */
689  int freq /**< new frequency of separator */
690  )
691 {
692  assert(sepa != NULL);
693 
694  sepa->freq = freq;
695 }
696 
697 /** get maximal bound distance at which the separator is called */
699  SCIP_SEPA* sepa /**< separator */
700  )
701 {
702  assert(sepa != NULL);
703 
704  return sepa->maxbounddist;
705 }
706 
707 /** does the separator use a secondary SCIP instance? */
709  SCIP_SEPA* sepa /**< separator */
710  )
711 {
712  assert(sepa != NULL);
713 
714  return sepa->usessubscip;
715 }
716 
717 /** gets time in seconds used in this separator for setting up for next stages */
719  SCIP_SEPA* sepa /**< separator */
720  )
721 {
722  assert(sepa != NULL);
723 
724  return SCIPclockGetTime(sepa->setuptime);
725 }
726 
727 /** gets time in seconds used in this separator */
729  SCIP_SEPA* sepa /**< separator */
730  )
731 {
732  assert(sepa != NULL);
733 
734  return SCIPclockGetTime(sepa->sepaclock);
735 }
736 
737 /** gets the total number of times, the separator was called */
739  SCIP_SEPA* sepa /**< separator */
740  )
741 {
742  assert(sepa != NULL);
743 
744  return sepa->ncalls;
745 }
746 
747 /** gets the number of times, the separator was called at the current node */
749  SCIP_SEPA* sepa /**< separator */
750  )
751 {
752  assert(sepa != NULL);
753 
754  return sepa->ncallsatnode;
755 }
756 
757 /** gets total number of times, the separator detected a cutoff */
759  SCIP_SEPA* sepa /**< separator */
760  )
761 {
762  assert(sepa != NULL);
763 
764  return sepa->ncutoffs;
765 }
766 
767 /** gets the total number of cutting planes found by this separator */
769  SCIP_SEPA* sepa /**< separator */
770  )
771 {
772  assert(sepa != NULL);
773 
774  return sepa->ncutsfound;
775 }
776 
777 /** gets the total number of cutting planes applied to lp */
779  SCIP_SEPA* sepa /**< separator */
780  )
781 {
782  assert(sepa != NULL);
783 
784  return sepa->ncutsapplied;
785 }
786 
787 /** increase count of applied cuts */
789  SCIP_SEPA* sepa /**< separator */
790  )
791 {
792  assert( sepa != NULL );
793 
794  ++sepa->ncutsapplied;
795 }
796 
797 /** increase count of found cuts */
799  SCIP_SEPA* sepa /**< separator */
800  )
801 {
802  assert( sepa != NULL );
803 
804  ++sepa->ncutsfound;
805 }
806 
807 /** increase count of found cuts at current node */
809  SCIP_SEPA* sepa /**< separator */
810  )
811 {
812  assert( sepa != NULL );
813 
814  ++sepa->ncutsfoundatnode;
815 }
816 
817 /** gets the number of cutting planes found by this separator at the current node */
819  SCIP_SEPA* sepa /**< separator */
820  )
821 {
822  assert(sepa != NULL);
823 
824  return sepa->ncutsfoundatnode;
825 }
826 
827 /** gets total number of additional constraints added by this separator */
829  SCIP_SEPA* sepa /**< separator */
830  )
831 {
832  assert(sepa != NULL);
833 
834  return sepa->nconssfound;
835 }
836 
837 /** gets total number of domain reductions found by this separator */
839  SCIP_SEPA* sepa /**< separator */
840  )
841 {
842  assert(sepa != NULL);
843 
844  return sepa->ndomredsfound;
845 }
846 
847 /** should separator be delayed, if other separators found cuts? */
849  SCIP_SEPA* sepa /**< separator */
850  )
851 {
852  assert(sepa != NULL);
853 
854  return sepa->delay;
855 }
856 
857 /** was separation of the LP solution delayed at the last call? */
859  SCIP_SEPA* sepa /**< separator */
860  )
861 {
862  assert(sepa != NULL);
863 
864  return sepa->lpwasdelayed;
865 }
866 
867 /** was separation of the primal solution delayed at the last call? */
869  SCIP_SEPA* sepa /**< separator */
870  )
871 {
872  assert(sepa != NULL);
873 
874  return sepa->solwasdelayed;
875 }
876 
877 /** is separator initialized? */
879  SCIP_SEPA* sepa /**< separator */
880  )
881 {
882  assert(sepa != NULL);
883 
884  return sepa->initialized;
885 }
886