1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2021 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 visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15
16 /**@file presol.c
17 * @ingroup OTHER_CFILES
18 * @brief methods for presolvers
19 * @author Tobias Achterberg
20 * @author Timo Berthold
21 *
22 * @todo add maxrounds parameter for single timings, count number of runs of a presolver with given timing
23 */
24
25 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
26
27 #include <assert.h>
28 #include <string.h>
29
30 #include "scip/def.h"
31 #include "blockmemshell/memory.h"
32 #include "scip/set.h"
33 #include "scip/clock.h"
34 #include "scip/paramset.h"
35 #include "scip/scip.h"
36 #include "scip/pub_misc.h"
37 #include "scip/presol.h"
38
39 #include "scip/struct_presol.h"
40
41
42
43 /*
44 * presolver methods
45 */
46
47 /** compares two presolvers w. r. to their priority */
SCIP_DECL_SORTPTRCOMP(SCIPpresolComp)48 SCIP_DECL_SORTPTRCOMP(SCIPpresolComp)
49 { /*lint --e{715}*/
50 return ((SCIP_PRESOL*)elem2)->priority - ((SCIP_PRESOL*)elem1)->priority;
51 }
52
53 /** comparison method for sorting presolvers w.r.t. to their name */
SCIP_DECL_SORTPTRCOMP(SCIPpresolCompName)54 SCIP_DECL_SORTPTRCOMP(SCIPpresolCompName)
55 {
56 return strcmp(SCIPpresolGetName((SCIP_PRESOL*)elem1), SCIPpresolGetName((SCIP_PRESOL*)elem2));
57 }
58
59 /** method to call, when the priority of a presolver was changed */
60 static
SCIP_DECL_PARAMCHGD(paramChgdPresolPriority)61 SCIP_DECL_PARAMCHGD(paramChgdPresolPriority)
62 { /*lint --e{715}*/
63 SCIP_PARAMDATA* paramdata;
64
65 paramdata = SCIPparamGetData(param);
66 assert(paramdata != NULL);
67
68 /* use SCIPsetPresolPriority() to mark the presols unsorted */
69 SCIP_CALL( SCIPsetPresolPriority(scip, (SCIP_PRESOL*)paramdata, SCIPparamGetInt(param)) ); /*lint !e740*/
70
71 return SCIP_OKAY;
72 }
73
74 /** copies the given presolver to a new scip */
SCIPpresolCopyInclude(SCIP_PRESOL * presol,SCIP_SET * set)75 SCIP_RETCODE SCIPpresolCopyInclude(
76 SCIP_PRESOL* presol, /**< presolver */
77 SCIP_SET* set /**< SCIP_SET of SCIP to copy to */
78 )
79 {
80 assert(presol != NULL);
81 assert(set != NULL);
82 assert(set->scip != NULL);
83
84 if( presol->presolcopy != NULL )
85 {
86 SCIPsetDebugMsg(set, "including presolver %s in subscip %p\n", SCIPpresolGetName(presol), (void*)set->scip);
87 SCIP_CALL( presol->presolcopy(set->scip, presol) );
88 }
89 return SCIP_OKAY;
90 }
91
92 /** internal method for creating a presolver */
93 static
doPresolCreate(SCIP_PRESOL ** presol,SCIP_SET * set,SCIP_MESSAGEHDLR * messagehdlr,BMS_BLKMEM * blkmem,const char * name,const char * desc,int priority,int maxrounds,SCIP_PRESOLTIMING timing,SCIP_DECL_PRESOLCOPY ((* presolcopy)),SCIP_DECL_PRESOLFREE ((* presolfree)),SCIP_DECL_PRESOLINIT ((* presolinit)),SCIP_DECL_PRESOLEXIT ((* presolexit)),SCIP_DECL_PRESOLINITPRE ((* presolinitpre)),SCIP_DECL_PRESOLEXITPRE ((* presolexitpre)),SCIP_DECL_PRESOLEXEC ((* presolexec)),SCIP_PRESOLDATA * presoldata)94 SCIP_RETCODE doPresolCreate(
95 SCIP_PRESOL** presol, /**< pointer to store presolver */
96 SCIP_SET* set, /**< global SCIP settings */
97 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
98 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
99 const char* name, /**< name of presolver */
100 const char* desc, /**< description of presolver */
101 int priority, /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */
102 int maxrounds, /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
103 SCIP_PRESOLTIMING timing, /**< timing mask of the presolver */
104 SCIP_DECL_PRESOLCOPY ((*presolcopy)), /**< copy method of presolver or NULL if you don't want to copy your plugin into sub-SCIPs */
105 SCIP_DECL_PRESOLFREE ((*presolfree)), /**< destructor of presolver to free user data (called when SCIP is exiting) */
106 SCIP_DECL_PRESOLINIT ((*presolinit)), /**< initialization method of presolver (called after problem was transformed) */
107 SCIP_DECL_PRESOLEXIT ((*presolexit)), /**< deinitialization method of presolver (called before transformed problem is freed) */
108 SCIP_DECL_PRESOLINITPRE((*presolinitpre)),/**< presolving initialization method of presolver (called when presolving is about to begin) */
109 SCIP_DECL_PRESOLEXITPRE((*presolexitpre)),/**< presolving deinitialization method of presolver (called after presolving has been finished) */
110 SCIP_DECL_PRESOLEXEC ((*presolexec)), /**< execution method of presolver */
111 SCIP_PRESOLDATA* presoldata /**< presolver data */
112 )
113 {
114 char paramname[SCIP_MAXSTRLEN];
115 char paramdesc[SCIP_MAXSTRLEN];
116
117 assert(presol != NULL);
118 assert(name != NULL);
119 assert(desc != NULL);
120
121 /* the interface change from delay flags to timings cannot be recognized at compile time: Exit with an appropriate
122 * error message
123 */
124 if( timing < SCIP_PRESOLTIMING_NONE || timing > SCIP_PRESOLTIMING_MAX )
125 {
126 SCIPmessagePrintError("ERROR: 'PRESOLDELAY'-flag no longer available since SCIP 3.2, use an appropriate "
127 "'SCIP_PRESOLTIMING' for <%s> presolver instead.\n", name);
128
129 return SCIP_PARAMETERWRONGVAL;
130 }
131
132 SCIP_ALLOC( BMSallocMemory(presol) );
133 BMSclearMemory(*presol);
134
135 SCIP_ALLOC( BMSduplicateMemoryArray(&(*presol)->name, name, strlen(name)+1) );
136 SCIP_ALLOC( BMSduplicateMemoryArray(&(*presol)->desc, desc, strlen(desc)+1) );
137 (*presol)->presolcopy = presolcopy;
138 (*presol)->presolfree = presolfree;
139 (*presol)->presolinit = presolinit;
140 (*presol)->presolexit = presolexit;
141 (*presol)->presolinitpre = presolinitpre;
142 (*presol)->presolexitpre = presolexitpre;
143 (*presol)->presolexec = presolexec;
144 (*presol)->presoldata = presoldata;
145 SCIP_CALL( SCIPclockCreate(&(*presol)->setuptime, SCIP_CLOCKTYPE_DEFAULT) );
146 SCIP_CALL( SCIPclockCreate(&(*presol)->presolclock, SCIP_CLOCKTYPE_DEFAULT) );
147 (*presol)->initialized = FALSE;
148
149 /* add parameters */
150 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "presolving/%s/priority", name);
151 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "priority of presolver <%s>", name);
152 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
153 &(*presol)->priority, TRUE, priority, INT_MIN/4, INT_MAX/4,
154 paramChgdPresolPriority, (SCIP_PARAMDATA*)(*presol)) ); /*lint !e740*/
155
156 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "presolving/%s/maxrounds", name);
157 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
158 "maximal number of presolving rounds the presolver participates in (-1: no limit)",
159 &(*presol)->maxrounds, FALSE, maxrounds, -1, INT_MAX, NULL, NULL) ); /*lint !e740*/
160
161 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "presolving/%s/timing", name);
162 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "timing mask of presolver <%s> (%u:FAST, %u:MEDIUM, %u:EXHAUSTIVE, %u:FINAL)",
163 name, SCIP_PRESOLTIMING_FAST, SCIP_PRESOLTIMING_MEDIUM, SCIP_PRESOLTIMING_EXHAUSTIVE, SCIP_PRESOLTIMING_FINAL);
164 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
165 (int*)&(*presol)->timing, TRUE, (int)timing, (int) SCIP_PRESOLTIMING_FAST, (int) SCIP_PRESOLTIMING_MAX, NULL, NULL) ); /*lint !e740*/
166
167 return SCIP_OKAY;
168 }
169
170 /** creates a presolver */
SCIPpresolCreate(SCIP_PRESOL ** presol,SCIP_SET * set,SCIP_MESSAGEHDLR * messagehdlr,BMS_BLKMEM * blkmem,const char * name,const char * desc,int priority,int maxrounds,SCIP_PRESOLTIMING timing,SCIP_DECL_PRESOLCOPY ((* presolcopy)),SCIP_DECL_PRESOLFREE ((* presolfree)),SCIP_DECL_PRESOLINIT ((* presolinit)),SCIP_DECL_PRESOLEXIT ((* presolexit)),SCIP_DECL_PRESOLINITPRE ((* presolinitpre)),SCIP_DECL_PRESOLEXITPRE ((* presolexitpre)),SCIP_DECL_PRESOLEXEC ((* presolexec)),SCIP_PRESOLDATA * presoldata)171 SCIP_RETCODE SCIPpresolCreate(
172 SCIP_PRESOL** presol, /**< pointer to store presolver */
173 SCIP_SET* set, /**< global SCIP settings */
174 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
175 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
176 const char* name, /**< name of presolver */
177 const char* desc, /**< description of presolver */
178 int priority, /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */
179 int maxrounds, /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
180 SCIP_PRESOLTIMING timing, /**< timing mask of the presolver */
181 SCIP_DECL_PRESOLCOPY ((*presolcopy)), /**< copy method of presolver or NULL if you don't want to copy your plugin into sub-SCIPs */
182 SCIP_DECL_PRESOLFREE ((*presolfree)), /**< destructor of presolver to free user data (called when SCIP is exiting) */
183 SCIP_DECL_PRESOLINIT ((*presolinit)), /**< initialization method of presolver (called after problem was transformed) */
184 SCIP_DECL_PRESOLEXIT ((*presolexit)), /**< deinitialization method of presolver (called before transformed problem is freed) */
185 SCIP_DECL_PRESOLINITPRE((*presolinitpre)),/**< presolving initialization method of presolver (called when presolving is about to begin) */
186 SCIP_DECL_PRESOLEXITPRE((*presolexitpre)),/**< presolving deinitialization method of presolver (called after presolving has been finished) */
187 SCIP_DECL_PRESOLEXEC ((*presolexec)), /**< execution method of presolver */
188 SCIP_PRESOLDATA* presoldata /**< presolver data */
189 )
190 {
191 assert(presol != NULL);
192 assert(name != NULL);
193 assert(desc != NULL);
194
195 SCIP_CALL_FINALLY( doPresolCreate(presol, set, messagehdlr, blkmem, name, desc, priority, maxrounds, timing,
196 presolcopy, presolfree, presolinit, presolexit, presolinitpre, presolexitpre, presolexec, presoldata),
197 (void) SCIPpresolFree(presol, set) );
198
199 return SCIP_OKAY;
200 }
201
202 /** frees memory of presolver */
SCIPpresolFree(SCIP_PRESOL ** presol,SCIP_SET * set)203 SCIP_RETCODE SCIPpresolFree(
204 SCIP_PRESOL** presol, /**< pointer to presolver data structure */
205 SCIP_SET* set /**< global SCIP settings */
206 )
207 {
208 assert(presol != NULL);
209 if( *presol == NULL )
210 return SCIP_OKAY;
211 assert(!(*presol)->initialized);
212 assert(set != NULL);
213
214 /* call destructor of presolver */
215 if( (*presol)->presolfree != NULL )
216 {
217 SCIP_CALL( (*presol)->presolfree(set->scip, *presol) );
218 }
219
220 SCIPclockFree(&(*presol)->presolclock);
221 SCIPclockFree(&(*presol)->setuptime);
222 BMSfreeMemoryArrayNull(&(*presol)->name);
223 BMSfreeMemoryArrayNull(&(*presol)->desc);
224 BMSfreeMemory(presol);
225
226 return SCIP_OKAY;
227 }
228
229 /** initializes presolver */
SCIPpresolInit(SCIP_PRESOL * presol,SCIP_SET * set)230 SCIP_RETCODE SCIPpresolInit(
231 SCIP_PRESOL* presol, /**< presolver */
232 SCIP_SET* set /**< global SCIP settings */
233 )
234 {
235 assert(presol != NULL);
236 assert(set != NULL);
237
238 if( presol->initialized )
239 {
240 SCIPerrorMessage("presolver <%s> already initialized\n", presol->name);
241 return SCIP_INVALIDCALL;
242 }
243
244 if( set->misc_resetstat )
245 {
246 SCIPclockReset(presol->setuptime);
247 SCIPclockReset(presol->presolclock);
248
249 presol->lastnfixedvars = 0;
250 presol->lastnaggrvars = 0;
251 presol->lastnchgvartypes = 0;
252 presol->lastnchgbds = 0;
253 presol->lastnaddholes = 0;
254 presol->lastndelconss = 0;
255 presol->lastnaddconss = 0;
256 presol->lastnupgdconss = 0;
257 presol->lastnchgcoefs = 0;
258 presol->lastnchgsides = 0;
259 presol->nfixedvars = 0;
260 presol->naggrvars = 0;
261 presol->nchgvartypes = 0;
262 presol->nchgbds = 0;
263 presol->naddholes = 0;
264 presol->ndelconss = 0;
265 presol->naddconss = 0;
266 presol->nupgdconss = 0;
267 presol->nchgcoefs = 0;
268 presol->nchgsides = 0;
269 presol->ncalls = 0;
270 }
271
272 /* call initialization method of presolver */
273 if( presol->presolinit != NULL )
274 {
275 /* start timing */
276 SCIPclockStart(presol->setuptime, set);
277
278 SCIP_CALL( presol->presolinit(set->scip, presol) );
279
280 /* stop timing */
281 SCIPclockStop(presol->setuptime, set);
282 }
283 presol->initialized = TRUE;
284
285 return SCIP_OKAY;
286 }
287
288 /** deinitializes presolver */
SCIPpresolExit(SCIP_PRESOL * presol,SCIP_SET * set)289 SCIP_RETCODE SCIPpresolExit(
290 SCIP_PRESOL* presol, /**< presolver */
291 SCIP_SET* set /**< global SCIP settings */
292 )
293 {
294 assert(presol != NULL);
295 assert(set != NULL);
296
297 if( !presol->initialized )
298 {
299 SCIPerrorMessage("presolver <%s> not initialized\n", presol->name);
300 return SCIP_INVALIDCALL;
301 }
302
303 /* call deinitialization method of presolver */
304 if( presol->presolexit != NULL )
305 {
306 /* start timing */
307 SCIPclockStart(presol->setuptime, set);
308
309 SCIP_CALL( presol->presolexit(set->scip, presol) );
310
311 /* stop timing */
312 SCIPclockStop(presol->setuptime, set);
313 }
314 presol->initialized = FALSE;
315
316 return SCIP_OKAY;
317 }
318
319 /** informs presolver that the presolving process is being started */
SCIPpresolInitpre(SCIP_PRESOL * presol,SCIP_SET * set)320 SCIP_RETCODE SCIPpresolInitpre(
321 SCIP_PRESOL* presol, /**< presolver */
322 SCIP_SET* set /**< global SCIP settings */
323 )
324 {
325 assert(presol != NULL);
326 assert(set != NULL);
327
328 presol->lastnfixedvars = 0;
329 presol->lastnaggrvars = 0;
330 presol->lastnchgvartypes = 0;
331 presol->lastnchgbds = 0;
332 presol->lastnaddholes = 0;
333 presol->lastndelconss = 0;
334 presol->lastnaddconss = 0;
335 presol->lastnupgdconss = 0;
336 presol->lastnchgcoefs = 0;
337 presol->lastnchgsides = 0;
338
339 /* call presolving initialization method of presolver */
340 if( presol->presolinitpre != NULL )
341 {
342 /* start timing */
343 SCIPclockStart(presol->setuptime, set);
344
345 SCIP_CALL( presol->presolinitpre(set->scip, presol) );
346
347 /* stop timing */
348 SCIPclockStop(presol->setuptime, set);
349 }
350
351 return SCIP_OKAY;
352 }
353
354 /** informs presolver that the presolving process is finished */
SCIPpresolExitpre(SCIP_PRESOL * presol,SCIP_SET * set)355 SCIP_RETCODE SCIPpresolExitpre(
356 SCIP_PRESOL* presol, /**< presolver */
357 SCIP_SET* set /**< global SCIP settings */
358 )
359 {
360 assert(presol != NULL);
361 assert(set != NULL);
362
363 /* call presolving deinitialization method of presolver */
364 if( presol->presolexitpre != NULL )
365 {
366 /* start timing */
367 SCIPclockStart(presol->setuptime, set);
368
369 SCIP_CALL( presol->presolexitpre(set->scip, presol) );
370
371 /* stop timing */
372 SCIPclockStop(presol->setuptime, set);
373 }
374
375 return SCIP_OKAY;
376 }
377
378 /** executes presolver */
SCIPpresolExec(SCIP_PRESOL * presol,SCIP_SET * set,SCIP_PRESOLTIMING timing,int nrounds,int * nfixedvars,int * naggrvars,int * nchgvartypes,int * nchgbds,int * naddholes,int * ndelconss,int * naddconss,int * nupgdconss,int * nchgcoefs,int * nchgsides,SCIP_RESULT * result)379 SCIP_RETCODE SCIPpresolExec(
380 SCIP_PRESOL* presol, /**< presolver */
381 SCIP_SET* set, /**< global SCIP settings */
382 SCIP_PRESOLTIMING timing, /**< current presolving timing */
383 int nrounds, /**< number of presolving rounds already done */
384 int* nfixedvars, /**< pointer to total number of variables fixed of all presolvers */
385 int* naggrvars, /**< pointer to total number of variables aggregated of all presolvers */
386 int* nchgvartypes, /**< pointer to total number of variable type changes of all presolvers */
387 int* nchgbds, /**< pointer to total number of variable bounds tightened of all presolvers */
388 int* naddholes, /**< pointer to total number of domain holes added of all presolvers */
389 int* ndelconss, /**< pointer to total number of deleted constraints of all presolvers */
390 int* naddconss, /**< pointer to total number of added constraints of all presolvers */
391 int* nupgdconss, /**< pointer to total number of upgraded constraints of all presolvers */
392 int* nchgcoefs, /**< pointer to total number of changed coefficients of all presolvers */
393 int* nchgsides, /**< pointer to total number of changed left/right hand sides of all presolvers */
394 SCIP_RESULT* result /**< pointer to store the result of the callback method */
395 )
396 {
397 int nnewfixedvars;
398 int nnewaggrvars;
399 int nnewchgvartypes;
400 int nnewchgbds;
401 int nnewaddholes;
402 int nnewdelconss;
403 int nnewaddconss;
404 int nnewupgdconss;
405 int nnewchgcoefs;
406 int nnewchgsides;
407
408 assert(presol != NULL);
409 assert(presol->presolexec != NULL);
410 assert(set != NULL);
411 assert(nfixedvars != NULL);
412 assert(naggrvars != NULL);
413 assert(nchgvartypes != NULL);
414 assert(nchgbds != NULL);
415 assert(naddholes != NULL);
416 assert(ndelconss != NULL);
417 assert(naddconss != NULL);
418 assert(nupgdconss != NULL);
419 assert(nchgcoefs != NULL);
420 assert(nchgsides != NULL);
421 assert(result != NULL);
422
423 *result = SCIP_DIDNOTRUN;
424
425 /* check number of presolving rounds */
426 if( presol->maxrounds >= 0 && presol->ncalls >= presol->maxrounds )
427 return SCIP_OKAY;
428
429 /* calculate the number of changes since last call */
430 nnewfixedvars = *nfixedvars - presol->lastnfixedvars;
431 nnewaggrvars = *naggrvars - presol->lastnaggrvars;
432 nnewchgvartypes = *nchgvartypes - presol->lastnchgvartypes;
433 nnewchgbds = *nchgbds - presol->lastnchgbds;
434 nnewaddholes = *naddholes - presol->lastnaddholes;
435 nnewdelconss = *ndelconss - presol->lastndelconss;
436 nnewaddconss = *naddconss - presol->lastnaddconss;
437 nnewupgdconss = *nupgdconss - presol->lastnupgdconss;
438 nnewchgcoefs = *nchgcoefs - presol->lastnchgcoefs;
439 nnewchgsides = *nchgsides - presol->lastnchgsides;
440
441 /* remember the number of changes prior to the call of the presolver */
442 presol->lastnfixedvars = *nfixedvars;
443 presol->lastnaggrvars = *naggrvars;
444 presol->lastnchgvartypes = *nchgvartypes;
445 presol->lastnchgbds = *nchgbds;
446 presol->lastnaddholes = *naddholes;
447 presol->lastndelconss = *ndelconss;
448 presol->lastnaddconss = *naddconss;
449 presol->lastnupgdconss = *nupgdconss;
450 presol->lastnchgcoefs = *nchgcoefs;
451 presol->lastnchgsides = *nchgsides;
452
453 /* check, if presolver should be called with the current timing */
454 if( timing & presol->timing )
455 {
456 SCIPsetDebugMsg(set, "calling presolver <%s> with timing %u\n", presol->name, timing);
457
458 /* start timing */
459 SCIPclockStart(presol->presolclock, set);
460
461 /* call external method */
462 SCIP_CALL( presol->presolexec(set->scip, presol, nrounds, timing,
463 nnewfixedvars, nnewaggrvars, nnewchgvartypes, nnewchgbds, nnewaddholes,
464 nnewdelconss, nnewaddconss, nnewupgdconss, nnewchgcoefs, nnewchgsides,
465 nfixedvars, naggrvars, nchgvartypes, nchgbds, naddholes,
466 ndelconss, naddconss, nupgdconss, nchgcoefs, nchgsides, result) );
467
468 /* stop timing */
469 SCIPclockStop(presol->presolclock, set);
470
471 /* add/count the new changes */
472 presol->nfixedvars += *nfixedvars - presol->lastnfixedvars;
473 presol->naggrvars += *naggrvars - presol->lastnaggrvars;
474 presol->nchgvartypes += *nchgvartypes - presol->lastnchgvartypes;
475 presol->nchgbds += *nchgbds - presol->lastnchgbds;
476 presol->naddholes += *naddholes - presol->lastnaddholes;
477 presol->ndelconss += *ndelconss - presol->lastndelconss;
478 presol->naddconss += *naddconss - presol->lastnaddconss;
479 presol->nupgdconss += *nupgdconss - presol->lastnupgdconss;
480 presol->nchgcoefs += *nchgcoefs - presol->lastnchgcoefs;
481 presol->nchgsides += *nchgsides - presol->lastnchgsides;
482
483 /* check result code of callback method */
484 if( *result != SCIP_CUTOFF
485 && *result != SCIP_UNBOUNDED
486 && *result != SCIP_SUCCESS
487 && *result != SCIP_DIDNOTFIND
488 && *result != SCIP_DIDNOTRUN )
489 {
490 SCIPerrorMessage("presolver <%s> returned invalid result <%d>\n", presol->name, *result);
491 return SCIP_INVALIDRESULT;
492 }
493
494 /* increase the number of calls, if the presolver tried to find reductions */
495 if( *result != SCIP_DIDNOTRUN )
496 ++(presol->ncalls);
497 }
498
499 return SCIP_OKAY;
500 }
501
502 /** gets user data of presolver */
SCIPpresolGetData(SCIP_PRESOL * presol)503 SCIP_PRESOLDATA* SCIPpresolGetData(
504 SCIP_PRESOL* presol /**< presolver */
505 )
506 {
507 assert(presol != NULL);
508
509 return presol->presoldata;
510 }
511
512 /** sets user data of presolver; user has to free old data in advance! */
SCIPpresolSetData(SCIP_PRESOL * presol,SCIP_PRESOLDATA * presoldata)513 void SCIPpresolSetData(
514 SCIP_PRESOL* presol, /**< presolver */
515 SCIP_PRESOLDATA* presoldata /**< new presolver user data */
516 )
517 {
518 assert(presol != NULL);
519
520 presol->presoldata = presoldata;
521 }
522
523 /** sets copy method of presolver */
SCIPpresolSetCopy(SCIP_PRESOL * presol,SCIP_DECL_PRESOLCOPY ((* presolcopy)))524 void SCIPpresolSetCopy(
525 SCIP_PRESOL* presol, /**< presolver */
526 SCIP_DECL_PRESOLCOPY ((*presolcopy)) /**< copy method of presolver or NULL if you don't want to copy your plugin into sub-SCIPs */
527 )
528 {
529 assert(presol != NULL);
530
531 presol->presolcopy = presolcopy;
532 }
533
534 /** sets destructor method of presolver */
SCIPpresolSetFree(SCIP_PRESOL * presol,SCIP_DECL_PRESOLFREE ((* presolfree)))535 void SCIPpresolSetFree(
536 SCIP_PRESOL* presol, /**< presolver */
537 SCIP_DECL_PRESOLFREE ((*presolfree)) /**< destructor of presolver */
538 )
539 {
540 assert(presol != NULL);
541
542 presol->presolfree = presolfree;
543 }
544
545 /** sets initialization method of presolver */
SCIPpresolSetInit(SCIP_PRESOL * presol,SCIP_DECL_PRESOLINIT ((* presolinit)))546 void SCIPpresolSetInit(
547 SCIP_PRESOL* presol, /**< presolver */
548 SCIP_DECL_PRESOLINIT ((*presolinit)) /**< initialize presolver */
549 )
550 {
551 assert(presol != NULL);
552
553 presol->presolinit = presolinit;
554 }
555
556 /** sets deinitialization method of presolver */
SCIPpresolSetExit(SCIP_PRESOL * presol,SCIP_DECL_PRESOLEXIT ((* presolexit)))557 void SCIPpresolSetExit(
558 SCIP_PRESOL* presol, /**< presolver */
559 SCIP_DECL_PRESOLEXIT ((*presolexit)) /**< deinitialize presolver */
560 )
561 {
562 assert(presol != NULL);
563
564 presol->presolexit = presolexit;
565 }
566
567 /** sets solving process initialization method of presolver */
SCIPpresolSetInitpre(SCIP_PRESOL * presol,SCIP_DECL_PRESOLINITPRE ((* presolinitpre)))568 void SCIPpresolSetInitpre(
569 SCIP_PRESOL* presol, /**< presolver */
570 SCIP_DECL_PRESOLINITPRE ((*presolinitpre))/**< solving process initialization method of presolver */
571 )
572 {
573 assert(presol != NULL);
574
575 presol->presolinitpre = presolinitpre;
576 }
577
578 /** sets solving process deinitialization method of presolver */
SCIPpresolSetExitpre(SCIP_PRESOL * presol,SCIP_DECL_PRESOLEXITPRE ((* presolexitpre)))579 void SCIPpresolSetExitpre(
580 SCIP_PRESOL* presol, /**< presolver */
581 SCIP_DECL_PRESOLEXITPRE ((*presolexitpre))/**< solving process deinitialization method of presolver */
582 )
583 {
584 assert(presol != NULL);
585
586 presol->presolexitpre = presolexitpre;
587 }
588
589 /** gets name of presolver */
SCIPpresolGetName(SCIP_PRESOL * presol)590 const char* SCIPpresolGetName(
591 SCIP_PRESOL* presol /**< presolver */
592 )
593 {
594 assert(presol != NULL);
595
596 return presol->name;
597 }
598
599 /** gets description of presolver */
SCIPpresolGetDesc(SCIP_PRESOL * presol)600 const char* SCIPpresolGetDesc(
601 SCIP_PRESOL* presol /**< presolver */
602 )
603 {
604 assert(presol != NULL);
605
606 return presol->desc;
607 }
608
609 /** gets priority of presolver */
SCIPpresolGetPriority(SCIP_PRESOL * presol)610 int SCIPpresolGetPriority(
611 SCIP_PRESOL* presol /**< presolver */
612 )
613 {
614 assert(presol != NULL);
615
616 return presol->priority;
617 }
618
619 /** gets round limit of presolver */
SCIPpresolGetMaxrounds(SCIP_PRESOL * presol)620 int SCIPpresolGetMaxrounds(
621 SCIP_PRESOL* presol /**< presolver */
622 )
623 {
624 assert(presol != NULL);
625
626 return presol->maxrounds;
627 }
628
629 /** sets priority of presolver */
SCIPpresolSetPriority(SCIP_PRESOL * presol,SCIP_SET * set,int priority)630 void SCIPpresolSetPriority(
631 SCIP_PRESOL* presol, /**< presolver */
632 SCIP_SET* set, /**< global SCIP settings */
633 int priority /**< new priority of the presolver */
634 )
635 {
636 assert(presol != NULL);
637 assert(set != NULL);
638
639 presol->priority = priority;
640 set->presolssorted = FALSE;
641 }
642
643 /** gets the timing mask of the presolver */
SCIPpresolGetTiming(SCIP_PRESOL * presol)644 SCIP_PRESOLTIMING SCIPpresolGetTiming(
645 SCIP_PRESOL* presol /**< presolver */
646 )
647 {
648 assert(presol != NULL);
649
650 return presol->timing;
651 }
652
653 /** sets the timing mask of the presolver */
SCIPpresolSetTiming(SCIP_PRESOL * presol,SCIP_PRESOLTIMING timing)654 void SCIPpresolSetTiming(
655 SCIP_PRESOL* presol, /**< presolver */
656 SCIP_PRESOLTIMING timing /**< timing mask of the presolver */
657 )
658 {
659 assert(presol != NULL);
660
661 presol->timing = timing;
662 }
663
664
665 /** is presolver initialized? */
SCIPpresolIsInitialized(SCIP_PRESOL * presol)666 SCIP_Bool SCIPpresolIsInitialized(
667 SCIP_PRESOL* presol /**< presolver */
668 )
669 {
670 assert(presol != NULL);
671
672 return presol->initialized;
673 }
674
675 /** enables or disables all clocks of \p presol, depending on the value of the flag */
SCIPpresolEnableOrDisableClocks(SCIP_PRESOL * presol,SCIP_Bool enable)676 void SCIPpresolEnableOrDisableClocks(
677 SCIP_PRESOL* presol, /**< the presolver for which all clocks should be enabled or disabled */
678 SCIP_Bool enable /**< should the clocks of the presolver be enabled? */
679 )
680 {
681 assert(presol != NULL);
682
683 SCIPclockEnableOrDisable(presol->setuptime, enable);
684 SCIPclockEnableOrDisable(presol->presolclock, enable);
685 }
686
687 /** gets time in seconds used in this presolver for setting up for next stages */
SCIPpresolGetSetupTime(SCIP_PRESOL * presol)688 SCIP_Real SCIPpresolGetSetupTime(
689 SCIP_PRESOL* presol /**< presolver */
690 )
691 {
692 assert(presol != NULL);
693
694 return SCIPclockGetTime(presol->setuptime);
695 }
696
697 /** gets time in seconds used in this presolver */
SCIPpresolGetTime(SCIP_PRESOL * presol)698 SCIP_Real SCIPpresolGetTime(
699 SCIP_PRESOL* presol /**< presolver */
700 )
701 {
702 assert(presol != NULL);
703
704 return SCIPclockGetTime(presol->presolclock);
705 }
706
707 /** gets number of variables fixed in presolver */
SCIPpresolGetNFixedVars(SCIP_PRESOL * presol)708 int SCIPpresolGetNFixedVars(
709 SCIP_PRESOL* presol /**< presolver */
710 )
711 {
712 assert(presol != NULL);
713
714 return presol->nfixedvars;
715 }
716
717 /** gets number of variables aggregated in presolver */
SCIPpresolGetNAggrVars(SCIP_PRESOL * presol)718 int SCIPpresolGetNAggrVars(
719 SCIP_PRESOL* presol /**< presolver */
720 )
721 {
722 assert(presol != NULL);
723
724 return presol->naggrvars;
725 }
726
727 /** gets number of variable types changed in presolver */
SCIPpresolGetNChgVarTypes(SCIP_PRESOL * presol)728 int SCIPpresolGetNChgVarTypes(
729 SCIP_PRESOL* presol /**< presolver */
730 )
731 {
732 assert(presol != NULL);
733
734 return presol->nchgvartypes;
735 }
736
737 /** gets number of bounds changed in presolver */
SCIPpresolGetNChgBds(SCIP_PRESOL * presol)738 int SCIPpresolGetNChgBds(
739 SCIP_PRESOL* presol /**< presolver */
740 )
741 {
742 assert(presol != NULL);
743
744 return presol->nchgbds;
745 }
746
747 /** gets number of holes added to domains of variables in presolver */
SCIPpresolGetNAddHoles(SCIP_PRESOL * presol)748 int SCIPpresolGetNAddHoles(
749 SCIP_PRESOL* presol /**< presolver */
750 )
751 {
752 assert(presol != NULL);
753
754 return presol->naddholes;
755 }
756
757 /** gets number of constraints deleted in presolver */
SCIPpresolGetNDelConss(SCIP_PRESOL * presol)758 int SCIPpresolGetNDelConss(
759 SCIP_PRESOL* presol /**< presolver */
760 )
761 {
762 assert(presol != NULL);
763
764 return presol->ndelconss;
765 }
766
767 /** gets number of constraints added in presolver */
SCIPpresolGetNAddConss(SCIP_PRESOL * presol)768 int SCIPpresolGetNAddConss(
769 SCIP_PRESOL* presol /**< presolver */
770 )
771 {
772 assert(presol != NULL);
773
774 return presol->naddconss;
775 }
776
777 /** gets number of constraints upgraded in presolver */
SCIPpresolGetNUpgdConss(SCIP_PRESOL * presol)778 int SCIPpresolGetNUpgdConss(
779 SCIP_PRESOL* presol /**< presolver */
780 )
781 {
782 assert(presol != NULL);
783
784 return presol->nupgdconss;
785 }
786
787 /** gets number of coefficients changed in presolver */
SCIPpresolGetNChgCoefs(SCIP_PRESOL * presol)788 int SCIPpresolGetNChgCoefs(
789 SCIP_PRESOL* presol /**< presolver */
790 )
791 {
792 assert(presol != NULL);
793
794 return presol->nchgcoefs;
795 }
796
797 /** gets number of constraint sides changed in presolver */
SCIPpresolGetNChgSides(SCIP_PRESOL * presol)798 int SCIPpresolGetNChgSides(
799 SCIP_PRESOL* presol /**< presolver */
800 )
801 {
802 assert(presol != NULL);
803
804 return presol->nchgsides;
805 }
806
807 /** gets number of times the presolver was called and tried to find reductions */
SCIPpresolGetNCalls(SCIP_PRESOL * presol)808 int SCIPpresolGetNCalls(
809 SCIP_PRESOL* presol /**< presolver */
810 )
811 {
812 assert(presol != NULL);
813
814 return presol->ncalls;
815 }
816