Scippy

SCIP

Solving Constraint Integer Programs

pricer.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 pricer.c
17  * @brief methods for variable pricers
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/clock.h"
30 #include "scip/paramset.h"
31 #include "scip/lp.h"
32 #include "scip/prob.h"
33 #include "scip/pricestore.h"
34 #include "scip/scip.h"
35 #include "scip/pricer.h"
36 #include "scip/pub_message.h"
37 #include "scip/pub_misc.h"
38 
39 #include "scip/struct_pricer.h"
40 
41 
42 
43 /** compares two pricers w. r. to their activity and their priority */
44 SCIP_DECL_SORTPTRCOMP(SCIPpricerComp)
45 { /*lint --e{715}*/
46  if( ((SCIP_PRICER*)elem1)->active != ((SCIP_PRICER*)elem2)->active )
47  return ((SCIP_PRICER*)elem1)->active ? -1 : +1;
48  else
49  return ((SCIP_PRICER*)elem2)->priority - ((SCIP_PRICER*)elem1)->priority;
50 }
51 
52 /** comparison method for sorting pricers w.r.t. to their name */
53 SCIP_DECL_SORTPTRCOMP(SCIPpricerCompName)
54 {
55  if( ((SCIP_PRICER*)elem1)->active != ((SCIP_PRICER*)elem2)->active )
56  return ((SCIP_PRICER*)elem1)->active ? -1 : +1;
57  else
58  return strcmp(SCIPpricerGetName((SCIP_PRICER*)elem1), SCIPpricerGetName((SCIP_PRICER*)elem2));
59 }
60 
61 /** method to call, when the priority of a pricer was changed */
62 static
63 SCIP_DECL_PARAMCHGD(paramChgdPricerPriority)
64 { /*lint --e{715}*/
65  SCIP_PARAMDATA* paramdata;
66 
67  paramdata = SCIPparamGetData(param);
68  assert(paramdata != NULL);
69 
70  /* use SCIPsetPricerPriority() to mark the pricers unsorted */
71  SCIP_CALL( SCIPsetPricerPriority(scip, (SCIP_PRICER*)paramdata, SCIPparamGetInt(param)) ); /*lint !e740*/
72 
73  return SCIP_OKAY;
74 }
75 
76 /** copies the given pricer to a new scip */
78  SCIP_PRICER* pricer, /**< pricer */
79  SCIP_SET* set, /**< SCIP_SET of SCIP to copy to */
80  SCIP_Bool* valid /**< was the copying process valid? */
81  )
82 {
83  assert(pricer != NULL);
84  assert(set != NULL);
85  assert(valid != NULL);
86  assert(set->scip != NULL);
87 
88  if( pricer->pricercopy != NULL )
89  {
90  SCIPdebugMessage("including pricer %s in subscip %p\n", SCIPpricerGetName(pricer), (void*)set->scip);
91  SCIP_CALL( pricer->pricercopy(set->scip, pricer, valid) );
92  }
93  return SCIP_OKAY;
94 }
95 
96 /** creates a variable pricer
97  * To use the variable pricer for solving a problem, it first has to be activated with a call to SCIPactivatePricer().
98  */
100  SCIP_PRICER** pricer, /**< pointer to variable pricer data structure */
101  SCIP_SET* set, /**< global SCIP settings */
102  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
103  BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
104  const char* name, /**< name of variable pricer */
105  const char* desc, /**< description of variable pricer */
106  int priority, /**< priority of the variable pricer */
107  SCIP_Bool delay, /**< should the pricer be delayed until no other pricers or already existing
108  * problem variables with negative reduced costs are found */
109  SCIP_DECL_PRICERCOPY ((*pricercopy)), /**< copy method of pricer or NULL if you don't want to copy your plugin into sub-SCIPs */
110  SCIP_DECL_PRICERFREE ((*pricerfree)), /**< destructor of variable pricer */
111  SCIP_DECL_PRICERINIT ((*pricerinit)), /**< initialize variable pricer */
112  SCIP_DECL_PRICEREXIT ((*pricerexit)), /**< deinitialize variable pricer */
113  SCIP_DECL_PRICERINITSOL((*pricerinitsol)),/**< solving process initialization method of variable pricer */
114  SCIP_DECL_PRICEREXITSOL((*pricerexitsol)),/**< solving process deinitialization method of variable pricer */
115  SCIP_DECL_PRICERREDCOST((*pricerredcost)),/**< reduced cost pricing method of variable pricer for feasible LPs */
116  SCIP_DECL_PRICERFARKAS((*pricerfarkas)), /**< Farkas pricing method of variable pricer for infeasible LPs */
117  SCIP_PRICERDATA* pricerdata /**< variable pricer data */
118  )
119 {
121  char paramdesc[SCIP_MAXSTRLEN];
122 
123  assert(pricer != NULL);
124  assert(name != NULL);
125  assert(desc != NULL);
126  assert(pricerredcost != NULL);
127 
128  SCIP_ALLOC( BMSallocMemory(pricer) );
129  SCIP_ALLOC( BMSduplicateMemoryArray(&(*pricer)->name, name, strlen(name)+1) );
130  SCIP_ALLOC( BMSduplicateMemoryArray(&(*pricer)->desc, desc, strlen(desc)+1) );
131  (*pricer)->priority = priority;
132  (*pricer)->pricercopy = pricercopy;
133  (*pricer)->pricerfree = pricerfree;
134  (*pricer)->pricerinit = pricerinit;
135  (*pricer)->pricerexit = pricerexit;
136  (*pricer)->pricerinitsol = pricerinitsol;
137  (*pricer)->pricerexitsol = pricerexitsol;
138  (*pricer)->pricerredcost = pricerredcost;
139  (*pricer)->pricerfarkas = pricerfarkas;
140  (*pricer)->pricerdata = pricerdata;
141  SCIP_CALL( SCIPclockCreate(&(*pricer)->setuptime, SCIP_CLOCKTYPE_DEFAULT) );
142  SCIP_CALL( SCIPclockCreate(&(*pricer)->pricerclock, SCIP_CLOCKTYPE_DEFAULT) );
143  (*pricer)->ncalls = 0;
144  (*pricer)->nvarsfound = 0;
145  (*pricer)->delay = delay;
146  (*pricer)->active = FALSE;
147  (*pricer)->initialized = FALSE;
148 
149  /* add parameters */
150  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "pricers/%s/priority", name);
151  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "priority of pricer <%s>", name);
152  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
153  &(*pricer)->priority, FALSE, priority, INT_MIN/4, INT_MAX/4,
154  paramChgdPricerPriority, (SCIP_PARAMDATA*)(*pricer)) ); /*lint !e740*/
155 
156  return SCIP_OKAY;
157 }
158 
159 /** calls destructor and frees memory of variable pricer */
161  SCIP_PRICER** pricer, /**< pointer to variable pricer data structure */
162  SCIP_SET* set /**< global SCIP settings */
163  )
164 {
165  assert(pricer != NULL);
166  assert(*pricer != NULL);
167  assert(!(*pricer)->initialized);
168  assert(set != NULL);
169 
170  /* call destructor of variable pricer */
171  if( (*pricer)->pricerfree != NULL )
172  {
173  SCIP_CALL( (*pricer)->pricerfree(set->scip, *pricer) );
174  }
175 
176  SCIPclockFree(&(*pricer)->pricerclock);
177  SCIPclockFree(&(*pricer)->setuptime);
178  BMSfreeMemoryArray(&(*pricer)->name);
179  BMSfreeMemoryArray(&(*pricer)->desc);
180  BMSfreeMemory(pricer);
181 
182  return SCIP_OKAY;
183 }
184 
185 /** initializes variable pricer */
187  SCIP_PRICER* pricer, /**< variable pricer */
188  SCIP_SET* set /**< global SCIP settings */
189  )
190 {
191  assert(pricer != NULL);
192  assert(pricer->active);
193  assert(set != NULL);
194 
195  if( pricer->initialized )
196  {
197  SCIPerrorMessage("variable pricer <%s> already initialized\n", pricer->name);
198  return SCIP_INVALIDCALL;
199  }
200 
201  if( set->misc_resetstat )
202  {
203  SCIPclockReset(pricer->setuptime);
204  SCIPclockReset(pricer->pricerclock);
205 
206  pricer->ncalls = 0;
207  pricer->nvarsfound = 0;
208  }
209 
210  if( pricer->pricerinit != NULL )
211  {
212  /* start timing */
213  SCIPclockStart(pricer->setuptime, set);
214 
215  SCIP_CALL( pricer->pricerinit(set->scip, pricer) );
216 
217  /* stop timing */
218  SCIPclockStop(pricer->setuptime, set);
219  }
220  pricer->initialized = TRUE;
221 
222  return SCIP_OKAY;
223 }
224 
225 /** calls exit method of variable pricer */
227  SCIP_PRICER* pricer, /**< variable pricer */
228  SCIP_SET* set /**< global SCIP settings */
229  )
230 {
231  assert(pricer != NULL);
232  assert(pricer->active);
233  assert(set != NULL);
234 
235  if( !pricer->initialized )
236  {
237  SCIPerrorMessage("variable pricer <%s> not initialized\n", pricer->name);
238  return SCIP_INVALIDCALL;
239  }
240 
241  if( pricer->pricerexit != NULL )
242  {
243  /* start timing */
244  SCIPclockStart(pricer->setuptime, set);
245 
246  SCIP_CALL( pricer->pricerexit(set->scip, pricer) );
247 
248  /* stop timing */
249  SCIPclockStop(pricer->setuptime, set);
250  }
251  pricer->initialized = FALSE;
252 
253  return SCIP_OKAY;
254 }
255 
256 /** informs variable pricer that the branch and bound process is being started */
258  SCIP_PRICER* pricer, /**< variable pricer */
259  SCIP_SET* set /**< global SCIP settings */
260  )
261 {
262  assert(pricer != NULL);
263  assert(set != NULL);
264 
265  /* call solving process initialization method of variable pricer */
266  if( pricer->pricerinitsol != NULL )
267  {
268  /* start timing */
269  SCIPclockStart(pricer->setuptime, set);
270 
271  SCIP_CALL( pricer->pricerinitsol(set->scip, pricer) );
272 
273  /* stop timing */
274  SCIPclockStop(pricer->setuptime, set);
275  }
276 
277  return SCIP_OKAY;
278 }
279 
280 /** informs variable pricer that the branch and bound process data is being freed */
282  SCIP_PRICER* pricer, /**< variable pricer */
283  SCIP_SET* set /**< global SCIP settings */
284  )
285 {
286  assert(pricer != NULL);
287  assert(set != NULL);
288 
289  /* call solving process deinitialization method of variable pricer */
290  if( pricer->pricerexitsol != NULL )
291  {
292  /* start timing */
293  SCIPclockStart(pricer->setuptime, set);
294 
295  SCIP_CALL( pricer->pricerexitsol(set->scip, pricer) );
296 
297  /* stop timing */
298  SCIPclockStop(pricer->setuptime, set);
299  }
300 
301  return SCIP_OKAY;
302 }
303 
304 /** activates pricer such that it is called in LP solving loop */
306  SCIP_PRICER* pricer, /**< variable pricer */
307  SCIP_SET* set /**< global SCIP settings */
308  )
309 {
310  assert(pricer != NULL);
311  assert(set != NULL);
312  assert(set->stage == SCIP_STAGE_PROBLEM);
313 
314  if( !pricer->active )
315  {
316  pricer->active = TRUE;
317  set->nactivepricers++;
318  set->pricerssorted = FALSE;
319  }
320 
321  return SCIP_OKAY;
322 }
323 
324 /** deactivates pricer such that it is no longer called in LP solving loop */
326  SCIP_PRICER* pricer, /**< variable pricer */
327  SCIP_SET* set /**< global SCIP settings */
328  )
329 {
330  assert(pricer != NULL);
331  assert(set != NULL);
332  assert(set->stage == SCIP_STAGE_PROBLEM);
333 
334  if( pricer->active )
335  {
336  pricer->active = FALSE;
337  set->nactivepricers--;
338  set->pricerssorted = FALSE;
339  }
340 
341  return SCIP_OKAY;
342 }
343 
344 /** calls reduced cost pricing method of variable pricer */
346  SCIP_PRICER* pricer, /**< variable pricer */
347  SCIP_SET* set, /**< global SCIP settings */
348  SCIP_PROB* prob, /**< transformed problem */
349  SCIP_Real* lowerbound, /**< local lower bound computed by the pricer */
350  SCIP_Bool* stopearly, /**< should pricing be stopped, although new variables were added? */
351  SCIP_RESULT* result /**< result of the pricing process */
352  )
353 {
354  int oldnvars;
355 
356  assert(pricer != NULL);
357  assert(pricer->active);
358  assert(pricer->pricerredcost != NULL);
359  assert(set != NULL);
360  assert(prob != NULL);
361  assert(lowerbound != NULL);
362  assert(result != NULL);
363 
364  SCIPdebugMessage("executing reduced cost pricing of variable pricer <%s>\n", pricer->name);
365 
366  oldnvars = prob->nvars;
367 
368  /* start timing */
369  SCIPclockStart(pricer->pricerclock, set);
370 
371  /* call external method */
372  SCIP_CALL( pricer->pricerredcost(set->scip, pricer, lowerbound, stopearly, result) );
373 
374  /* stop timing */
375  SCIPclockStop(pricer->pricerclock, set);
376 
377  /* evaluate result */
378  pricer->ncalls++;
379  pricer->nvarsfound += prob->nvars - oldnvars;
380 
381  return SCIP_OKAY;
382 }
383 
384 /** calls Farkas pricing method of variable pricer */
386  SCIP_PRICER* pricer, /**< variable pricer */
387  SCIP_SET* set, /**< global SCIP settings */
388  SCIP_PROB* prob /**< transformed problem */
389  )
390 {
391  int oldnvars;
392 
393  assert(pricer != NULL);
394  assert(pricer->active);
395  assert(set != NULL);
396  assert(prob != NULL);
397 
398  /* check, if pricer implemented a Farkas pricing algorithm */
399  if( pricer->pricerfarkas == NULL )
400  return SCIP_OKAY;
401 
402  SCIPdebugMessage("executing Farkas pricing of variable pricer <%s>\n", pricer->name);
403 
404  oldnvars = prob->nvars;
405 
406  /* start timing */
407  SCIPclockStart(pricer->pricerclock, set);
408 
409  /* call external method */
410  SCIP_CALL( pricer->pricerfarkas(set->scip, pricer) );
411 
412  /* stop timing */
413  SCIPclockStop(pricer->pricerclock, set);
414 
415  /* evaluate result */
416  pricer->ncalls++;
417  pricer->nvarsfound += prob->nvars - oldnvars;
418 
419  return SCIP_OKAY;
420 }
421 
422 /** depending on the LP's solution status, calls reduced cost or Farkas pricing method of variable pricer */
424  SCIP_PRICER* pricer, /**< variable pricer */
425  SCIP_SET* set, /**< global SCIP settings */
426  SCIP_PROB* prob, /**< transformed problem */
427  SCIP_LP* lp, /**< LP data */
428  SCIP_PRICESTORE* pricestore, /**< pricing storage */
429  SCIP_Real* lowerbound, /**< local lower bound computed by the pricer */
430  SCIP_Bool* stopearly, /**< should pricing be stopped, although new variables were added? */
431  SCIP_RESULT* result /**< result of the pricing process */
432  )
433 {
434  assert(pricer != NULL);
435  assert(lowerbound != NULL);
436  assert(stopearly != NULL);
437  assert(result != NULL);
438 
439  /* set lowerbound, stopearly, and result pointer */
440  *lowerbound = - SCIPsetInfinity(set);
441  *stopearly = FALSE;
442  *result = SCIP_SUCCESS;
443 
444  /* check if pricer should be delayed */
445  if( pricer->delay && SCIPpricestoreGetNVars(pricestore) > 0 )
446  return SCIP_OKAY;
447 
449  {
450  SCIP_CALL( SCIPpricerFarkas(pricer, set, prob) );
451  }
452  else
453  {
454  *result = SCIP_DIDNOTRUN;
455  SCIP_CALL( SCIPpricerRedcost(pricer, set, prob, lowerbound, stopearly, result) );
456  }
457 
458  return SCIP_OKAY;
459 }
460 
461 /** gets user data of variable pricer */
463  SCIP_PRICER* pricer /**< variable pricer */
464  )
465 {
466  assert(pricer != NULL);
467 
468  return pricer->pricerdata;
469 }
470 
471 /** sets user data of variable pricer; user has to free old data in advance! */
473  SCIP_PRICER* pricer, /**< variable pricer */
474  SCIP_PRICERDATA* pricerdata /**< new variable pricer user data */
475  )
476 {
477  assert(pricer != NULL);
478 
479  pricer->pricerdata = pricerdata;
480 }
481 
482 /** sets copy callback of pricer */
484  SCIP_PRICER* pricer, /**< variable pricer */
485  SCIP_DECL_PRICERCOPY ((*pricercopy)) /**< copy callback of pricer */
486  )
487 {
488  assert(pricer != NULL);
489 
490  pricer->pricercopy = pricercopy;
491 }
492 
493 /** sets destructor callback of pricer */
495  SCIP_PRICER* pricer, /**< pricer */
496  SCIP_DECL_PRICERFREE ((*pricerfree)) /**< destructor of pricer */
497  )
498 {
499  assert(pricer != NULL);
500 
501  pricer->pricerfree = pricerfree;
502 }
503 
504 /** sets initialization callback of pricer */
506  SCIP_PRICER* pricer, /**< pricer */
507  SCIP_DECL_PRICERINIT ((*pricerinit)) /**< initialize pricer */
508  )
509 {
510  assert(pricer != NULL);
511 
512  pricer->pricerinit = pricerinit;
513 }
514 
515 /** sets deinitialization callback of pricer */
517  SCIP_PRICER* pricer, /**< pricer */
518  SCIP_DECL_PRICEREXIT ((*pricerexit)) /**< deinitialize pricer */
519  )
520 {
521  assert(pricer != NULL);
522 
523  pricer->pricerexit = pricerexit;
524 }
525 
526 /** sets solving process initialization callback of pricer */
528  SCIP_PRICER* pricer, /**< pricer */
529  SCIP_DECL_PRICERINITSOL ((*pricerinitsol))/**< solving process initialization callback of pricer */
530  )
531 {
532  assert(pricer != NULL);
533 
534  pricer->pricerinitsol = pricerinitsol;
535 }
536 
537 /** sets solving process deinitialization callback of pricer */
539  SCIP_PRICER* pricer, /**< pricer */
540  SCIP_DECL_PRICEREXITSOL ((*pricerexitsol))/**< solving process deinitialization callback of pricer */
541  )
542 {
543  assert(pricer != NULL);
544 
545  pricer->pricerexitsol = pricerexitsol;
546 }
547 
548 /** gets name of variable pricer */
549 const char* SCIPpricerGetName(
550  SCIP_PRICER* pricer /**< variable pricer */
551  )
552 {
553  assert(pricer != NULL);
554 
555  return pricer->name;
556 }
557 
558 /** gets description of variable pricer */
559 const char* SCIPpricerGetDesc(
560  SCIP_PRICER* pricer /**< variable pricer */
561  )
562 {
563  assert(pricer != NULL);
564 
565  return pricer->desc;
566 }
567 
568 /** gets priority of variable pricer */
570  SCIP_PRICER* pricer /**< variable pricer */
571  )
572 {
573  assert(pricer != NULL);
574 
575  return pricer->priority;
576 }
577 
578 /** sets priority of variable pricer */
580  SCIP_PRICER* pricer, /**< variable pricer */
581  SCIP_SET* set, /**< global SCIP settings */
582  int priority /**< new priority of the variable pricer */
583  )
584 {
585  assert(pricer != NULL);
586  assert(set != NULL);
587 
588  pricer->priority = priority;
589  set->pricerssorted = FALSE;
590 }
591 
592 /** gets the number of times, the pricer was called and tried to find a variable with negative reduced costs */
594  SCIP_PRICER* pricer /**< variable pricer */
595  )
596 {
597  assert(pricer != NULL);
598 
599  return pricer->ncalls;
600 }
601 
602 /** gets the number of variables with negative reduced costs found by this pricer */
604  SCIP_PRICER* pricer /**< variable pricer */
605  )
606 {
607  assert(pricer != NULL);
608 
609  return pricer->nvarsfound;
610 }
611 
612 /** gets time in seconds used in this pricer for setting up for next stages */
614  SCIP_PRICER* pricer /**< variable pricer */
615  )
616 {
617  assert(pricer != NULL);
618 
619  return SCIPclockGetTime(pricer->setuptime);
620 }
621 
622 /** gets time in seconds used in this pricer */
624  SCIP_PRICER* pricer /**< variable pricer */
625  )
626 {
627  assert(pricer != NULL);
628 
629  return SCIPclockGetTime(pricer->pricerclock);
630 }
631 
632 /** returns whether the given pricer is in use in the current problem */
634  SCIP_PRICER* pricer /**< variable pricer */
635  )
636 {
637  assert(pricer != NULL);
638 
639  return pricer->active;
640 }
641 
642 /** returns whether the pricer should be delayed until no other pricer finds a new variable */
644  SCIP_PRICER* pricer /**< variable pricer */
645  )
646 {
647  assert(pricer != NULL);
648 
649  return pricer->delay;
650 }
651 
652 /** is variable pricer initialized? */
654  SCIP_PRICER* pricer /**< variable pricer */
655  )
656 {
657  assert(pricer != NULL);
658 
659  return pricer->initialized;
660 }
661 
662 
663