Scippy

SCIP

Solving Constraint Integer Programs

cons_conjunction.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-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 cons_conjunction.c
17  * @ingroup DEFPLUGINS_CONS
18  * @brief constraint handler for conjunction constraints
19  * @author Tobias Achterberg
20  */
21 
22 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
23 
24 #include "blockmemshell/memory.h"
25 #include "scip/cons_conjunction.h"
26 #include "scip/pub_cons.h"
27 #include "scip/pub_message.h"
28 #include "scip/scip_cons.h"
29 #include "scip/scip_copy.h"
30 #include "scip/scip_general.h"
31 #include "scip/scip_mem.h"
32 #include "scip/scip_message.h"
33 #include "scip/scip_prob.h"
34 #include "scip/scip_sol.h"
35 #include <string.h>
36 
37 
38 
39 /* constraint handler properties */
40 #define CONSHDLR_NAME "conjunction"
41 #define CONSHDLR_DESC "conjunction of constraints"
42 #define CONSHDLR_ENFOPRIORITY +900000 /**< priority of the constraint handler for constraint enforcing */
43 #define CONSHDLR_CHECKPRIORITY -900000 /**< priority of the constraint handler for checking feasibility */
44 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
45  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
46 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
47 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
48 
49 #define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_FAST
50 
51 /*
52  * Data structures
53  */
54 
55 /** constraint data for conjunction constraints */
56 struct SCIP_ConsData
57 {
58  SCIP_CONS** conss; /**< constraints in conjunction */
59  int consssize; /**< size of conss array */
60  int nconss; /**< number of constraints in conjunction */
61 };
62 
63 
64 /*
65  * Local methods
66  */
67 
68 /** creates conjunction constraint data, captures initial constraints of conjunction */
69 static
71  SCIP* scip, /**< SCIP data structure */
72  SCIP_CONSDATA** consdata, /**< pointer to constraint data */
73  SCIP_CONS** conss, /**< initial constraint in conjunction */
74  int nconss /**< number of initial constraints in conjunction */
75  )
76 {
77  assert(consdata != NULL);
78 
79  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
80  if( nconss > 0 )
81  {
82  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->conss, conss, nconss) );
83  (*consdata)->consssize = nconss;
84  (*consdata)->nconss = nconss;
85 
86  if( SCIPisTransformed(scip) )
87  {
88  SCIP_CALL( SCIPtransformConss(scip, nconss, (*consdata)->conss, (*consdata)->conss) );
89  }
90  else
91  {
92  int c;
93 
94  for( c = 0; c < nconss; ++c )
95  {
96  SCIP_CALL( SCIPcaptureCons(scip, conss[c]) );
97  }
98  }
99  }
100  else
101  {
102  (*consdata)->conss = NULL;
103  (*consdata)->consssize = 0;
104  (*consdata)->nconss = 0;
105  }
106 
107  return SCIP_OKAY;
108 }
109 
110 /** frees constraint data and releases all constraints in conjunction */
111 static
113  SCIP* scip, /**< SCIP data structure */
114  SCIP_CONSDATA** consdata /**< pointer to constraint data */
115  )
116 {
117  int c;
118 
119  assert(consdata != NULL);
120  assert(*consdata != NULL);
121 
122  /* release constraints */
123  for( c = 0; c < (*consdata)->nconss; ++c )
124  {
125  SCIP_CALL( SCIPreleaseCons(scip, &(*consdata)->conss[c]) );
126  }
127 
128  /* free memory */
129  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->conss, (*consdata)->consssize);
130  SCIPfreeBlockMemory(scip, consdata);
131 
132  return SCIP_OKAY;
133 }
134 
135 /** adds constraint to conjunction */
136 static
138  SCIP* scip, /**< SCIP data structure */
139  SCIP_CONSDATA* consdata, /**< constraint data */
140  SCIP_CONS* cons /**< constraint to add to the conjunction */
141  )
142 {
143  assert(consdata != NULL);
144 
145  /* get memory for additional constraint */
146  SCIP_CALL( SCIPensureBlockMemoryArray(scip, &consdata->conss, &consdata->consssize, consdata->nconss+1) );
147  assert(consdata->conss != NULL);
148  assert(consdata->nconss < consdata->consssize);
149 
150  /* insert constraint in array */
151  consdata->conss[consdata->nconss] = cons;
152  consdata->nconss++;
153 
154  if( SCIPisTransformed(scip) )
155  {
156  SCIP_CALL( SCIPtransformCons(scip, consdata->conss[consdata->nconss - 1], &(consdata->conss[consdata->nconss - 1])) );
157  }
158  else
159  {
160  /* capture constraint */
161  SCIP_CALL( SCIPcaptureCons(scip, cons) );
162  }
163 
164  return SCIP_OKAY;
165 }
166 
167 /** adds all constraints in conjunction constraints to the problem; disables unmodifiable conjunction constraints */
168 static
170  SCIP* scip, /**< SCIP data structure */
171  SCIP_CONS** conss, /**< active conjunction constraints */
172  int nconss, /**< number of active conjunction constraints */
173  SCIP_RESULT* result /**< pointer to store the result */
174  )
175 {
176  SCIP_CONSDATA* consdata;
177  int c;
178  int i;
179 
180  assert(result != NULL);
181 
182  for( c = 0; c < nconss; ++c )
183  {
184  consdata = SCIPconsGetData(conss[c]);
185  assert(consdata != NULL);
186 
187  /* add all inactive constraints to local subproblem */
188  for( i = 0; i < consdata->nconss; ++i )
189  {
190  /* update check flag for sub constraints when upgrade takes place */
191  if( SCIPconsIsChecked(conss[c]) )
192  {
193  /* make sure, the constraint is checked for feasibility */
194  SCIP_CALL( SCIPsetConsChecked(scip, consdata->conss[i], TRUE) );
195  }
196 
197  if( !SCIPconsIsActive(consdata->conss[i]) )
198  {
199  SCIPdebugMsg(scip, "adding constraint <%s> from add conjunction <%s>\n",
200  SCIPconsGetName(consdata->conss[i]), SCIPconsGetName(conss[c]));
201  SCIP_CALL( SCIPaddConsLocal(scip, consdata->conss[i], NULL) );
202  *result = SCIP_CONSADDED;
203  }
204  }
205 
206  /* disable conjunction constraint, if it is unmodifiable */
207  if( !SCIPconsIsModifiable(conss[c]) )
208  {
209  SCIP_CALL( SCIPdelConsLocal(scip, conss[c]) );
210  }
211  }
212 
213  return SCIP_OKAY;
214 }
215 
216 /** checks all constraints in conjunction constraints for feasibility */
217 static
219  SCIP* scip, /**< SCIP data structure */
220  SCIP_CONS** conss, /**< active conjunction constraints */
221  int nconss, /**< number of active conjunction constraints */
222  SCIP_SOL* sol, /**< solution to check */
223  SCIP_Bool checkintegrality, /**< Has integrality to be checked? */
224  SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
225  SCIP_Bool printreason, /**< Should the reason for the violation be printed? */
226  SCIP_Bool completely, /**< Should all violations be checked? */
227  SCIP_RESULT* result /**< pointer to store the result */
228  )
229 {
230  SCIP_CONSDATA* consdata;
231  int c;
232  int i;
233 
234  assert(result != NULL);
235 
236  *result = SCIP_FEASIBLE;
237 
238  for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
239  {
240  SCIP_RESULT subresult = SCIP_FEASIBLE;
241 
242  consdata = SCIPconsGetData(conss[c]);
243  assert(consdata != NULL);
244 
245  /* check all constraints */
246  for( i = 0; i < consdata->nconss && subresult == SCIP_FEASIBLE; ++i )
247  {
248  SCIP_CALL( SCIPcheckCons(scip, consdata->conss[i], sol, checkintegrality, checklprows, printreason, &subresult) );
249  assert(subresult == SCIP_FEASIBLE || subresult == SCIP_INFEASIBLE);
250  }
251 
252  if( subresult == SCIP_INFEASIBLE )
253  {
254  /* mark solution as violated */
255  *result = SCIP_INFEASIBLE;
256  /* update constraint violation in solution */
257  if ( sol != NULL )
258  SCIPupdateSolConsViolation(scip, sol, 1.0, 1.0);
259  if( printreason )
260  {
261  assert( 0 < i && i <= consdata->nconss );
262  SCIPinfoMessage(scip, NULL, "Conjunction constraint %s is violated, at least the sub-constraint %s is violated by this given solution.\n",
263  SCIPconsGetName(conss[c]), SCIPconsGetName(consdata->conss[i-1]));
264  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, conss[c], NULL) ) );
265  }
266  }
267  }
268 
269  return SCIP_OKAY;
270 }
271 
272 
273 /*
274  * Callback methods of constraint handler
275  */
276 
277 
278  /** copy method for constraint handler plugins (called when SCIP copies plugins) */
279 static
280 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyConjunction)
281 { /*lint --e{715}*/
282  assert(scip != NULL);
283  assert(conshdlr != NULL);
284  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
285 
286  /* call inclusion method of constraint handler */
288 
289  *valid = TRUE;
290 
291  return SCIP_OKAY;
292 }
293 
294 
295 /** frees specific constraint data */
296 static
297 SCIP_DECL_CONSDELETE(consDeleteConjunction)
298 { /*lint --e{715}*/
299  SCIP_CALL( consdataFree(scip, consdata) );
300 
301  return SCIP_OKAY;
302 }
303 
304 /** transforms constraint data into data belonging to the transformed problem */
305 static
306 SCIP_DECL_CONSTRANS(consTransConjunction)
307 { /*lint --e{715}*/
308  SCIP_CONSDATA* sourcedata;
309  SCIP_CONSDATA* targetdata;
310  int c;
311 
312  /* create constraint data for target constraint */
313  SCIP_CALL( SCIPallocBlockMemory(scip, &targetdata) );
314 
315  /* get constraint data of source constraint */
316  sourcedata = SCIPconsGetData(sourcecons);
317 
318  if( sourcedata->nconss > 0 )
319  {
320  targetdata->consssize = sourcedata->nconss;
321  targetdata->nconss = sourcedata->nconss;
322  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &targetdata->conss, targetdata->consssize) );
323  for( c = 0; c < sourcedata->nconss; ++c )
324  {
325  SCIP_CALL( SCIPtransformCons(scip, sourcedata->conss[c], &targetdata->conss[c]) );
326  }
327  }
328  else
329  {
330  targetdata->conss = NULL;
331  targetdata->consssize = 0;
332  targetdata->nconss = 0;
333  }
334 
335  /* create target constraint */
336  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
337  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
338  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
339  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
340  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
341 
342  return SCIP_OKAY;
343 }
344 
345 
346 /** constraint enforcing method of constraint handler for LP solutions */
347 static
348 SCIP_DECL_CONSENFOLP(consEnfolpConjunction)
349 { /*lint --e{715}*/
350  *result = SCIP_FEASIBLE;
351 
352  /* add all constraints to the current node */
353  SCIP_CALL( addAllConss(scip, conss, nconss, result) );
354 
355  return SCIP_OKAY;
356 }
357 
358 
359 /** constraint enforcing method of constraint handler for relaxation solutions */
360 static
361 SCIP_DECL_CONSENFORELAX(consEnforelaxConjunction)
362 { /*lint --e{715}*/
363  *result = SCIP_FEASIBLE;
364 
365  /* add all constraints to the current node */
366  SCIP_CALL( addAllConss(scip, conss, nconss, result) );
367 
368  return SCIP_OKAY;
369 }
370 
371 
372 /** constraint enforcing method of constraint handler for pseudo solutions */
373 static
374 SCIP_DECL_CONSENFOPS(consEnfopsConjunction)
375 { /*lint --e{715}*/
376  *result = SCIP_FEASIBLE;
377 
378  /* add all constraints to the current node */
379  SCIP_CALL( addAllConss(scip, conss, nconss, result) );
380 
381  return SCIP_OKAY;
382 }
383 
384 
385 /** feasibility check method of constraint handler for integral solutions */
386 static
387 SCIP_DECL_CONSCHECK(consCheckConjunction)
388 { /*lint --e{715}*/
389  *result = SCIP_FEASIBLE;
390 
391  /* check all constraints of the conjunction */
392  SCIP_CALL( checkAllConss(scip, conss, nconss, sol, checkintegrality, checklprows, printreason, completely, result) );
393 
394  return SCIP_OKAY;
395 }
396 
397 
398 /** presolving method of constraint handler */
399 static
400 SCIP_DECL_CONSPRESOL(consPresolConjunction)
401 { /*lint --e{715}*/
402  SCIP_CONSDATA* consdata;
403  int c;
404  int i;
405 
406  assert(result != NULL);
407 
408  *result = SCIP_DIDNOTFIND;
409 
410  /* all constraints in a conjunction constraint of the global problem can be added directly to the problem and
411  * removed from the conjunction constraint;
412  * an unmodifiable conjunction constraint can be deleted
413  */
414  for( c = 0; c < nconss; ++c )
415  {
416  consdata = SCIPconsGetData(conss[c]);
417  assert(consdata != NULL);
418 
419  /* add all inactive constraints to the global problem */
420  for( i = 0; i < consdata->nconss; ++i )
421  {
422  /* update check flag for sub constraints when upgrade takes place */
423  if( SCIPconsIsChecked(conss[c]) )
424  {
425  /* make sure, the constraint is checked for feasibility */
426  SCIP_CALL( SCIPsetConsChecked(scip, consdata->conss[i], TRUE) );
427  }
428 
429  /* add constraint, if it is not active yet */
430  if( !SCIPconsIsActive(consdata->conss[i]) )
431  {
432  SCIPdebugMsg(scip, "adding constraint <%s> from add conjunction <%s>\n",
433  SCIPconsGetName(consdata->conss[i]), SCIPconsGetName(conss[c]));
434  SCIP_CALL( SCIPaddCons(scip, consdata->conss[i]) );
435  *result = SCIP_SUCCESS;
436  }
437  /* release constraint because it will be removed from the conjunction constraint */
438  SCIP_CALL( SCIPreleaseCons(scip, &(consdata->conss[i])) );
439  }
440  /* all constraints where removed, so we need to clear the array */
441  consdata->nconss = 0;
442 
443  /* delete conjunction constraint, if it is unmodifiable */
444  if( !SCIPconsIsModifiable(conss[c]) )
445  {
446  SCIP_CALL( SCIPdelCons(scip, conss[c]) );
447  }
448  }
449 
450  return SCIP_OKAY;
451 }
452 
453 
454 /** variable rounding lock method of constraint handler */
455 static
456 SCIP_DECL_CONSLOCK(consLockConjunction)
457 { /*lint --e{715}*/
458  SCIP_CONSDATA* consdata;
459  int c;
460 
461  assert(locktype == SCIP_LOCKTYPE_MODEL);
462 
463  consdata = SCIPconsGetData(cons);
464  assert(consdata != NULL);
465 
466  /* lock sub constraints */
467  for( c = 0; c < consdata->nconss; ++c )
468  {
469  SCIP_CALL( SCIPaddConsLocksType(scip, consdata->conss[c], locktype, nlockspos, nlocksneg) );
470  }
471 
472  return SCIP_OKAY;
473 }
474 
475 
476 /** constraint display method of constraint handler */
477 static
478 SCIP_DECL_CONSPRINT(consPrintConjunction)
479 { /*lint --e{715}*/
480  SCIP_CONSDATA* consdata;
481  int i;
482 
483  assert( scip != NULL );
484  assert( conshdlr != NULL );
485  assert( cons != NULL );
486 
487  consdata = SCIPconsGetData(cons);
488  assert(consdata != NULL);
489 
490  SCIPinfoMessage(scip, file, "conjunction(");
491 
492  for( i = 0; i < consdata->nconss; ++i )
493  {
494  if( i > 0 )
495  SCIPinfoMessage(scip, file, ", ");
496  SCIP_CALL( SCIPprintCons(scip, consdata->conss[i], file) );
497  }
498  SCIPinfoMessage(scip, file, ")");
499 
500  return SCIP_OKAY;
501 }
502 
503 /** constraint parsing method of constraint handler */
504 static
505 SCIP_DECL_CONSPARSE(consParseConjunction)
506 { /*lint --e{715}*/
507  SCIP_CONS** conss;
508  int nconss;
509  int sconss;
510  char* token;
511  char* saveptr;
512  char* nexttokenstart;
513  char* copystr;
514 
515  assert(scip != NULL);
516  assert(conshdlr != NULL);
517  assert(cons != NULL);
518  assert(success != NULL);
519  assert(str != NULL);
520  assert(name != NULL);
521 
522  SCIPdebugMsg(scip, "parsing conjunction <%s>\n", name);
523 
524  *success = TRUE;
525 
526  /* allocate memory for constraint in conjunction, initial size is set to 10 */
527  nconss = 0;
528  sconss = 10;
529  SCIP_CALL( SCIPallocBufferArray(scip, &conss, sconss) );
530  SCIP_CALL( SCIPduplicateBufferArray(scip, &copystr, str, (int)strlen(str)+1) );
531 
532  /* find '(' at the beginning, string should start with 'conjunction(' */
533  saveptr = strpbrk(copystr, "("); /*lint !e158*/
534 
535  if( saveptr == NULL )
536  {
537  SCIPdebugMsg(scip, "error parsing conjunctive constraint: \"%s\"\n", str);
538  *success = FALSE;
539  goto TERMINATE;
540  }
541  assert(saveptr != NULL); /* for lint */
542 
543  /* skip '(' */
544  ++saveptr;
545  /* remember token start position */
546  nexttokenstart = saveptr;
547 
548  /* brackets '(' and ')' can exist co we check for them and the constraint delimeter */
549  saveptr = strpbrk(saveptr, "(,");
550 
551  /* brackets '(' and ')' can exist in the rest of the string so we need to skip them to find the end of the first
552  * sub-constraint marked by a ','
553  */
554  if( saveptr != NULL )
555  {
556  do
557  {
558  int bracketcounter = 0;
559 
560  if( *saveptr == '(' )
561  {
562  do
563  {
564  ++bracketcounter;
565  ++saveptr;
566 
567  /* find last ending bracket */
568  while( bracketcounter > 0 )
569  {
570  saveptr = strpbrk(saveptr, "()");
571 
572  if( saveptr != NULL )
573  {
574  if( *saveptr == '(' )
575  ++bracketcounter;
576  else
577  --bracketcounter;
578 
579  ++saveptr;
580  }
581  else
582  {
583  SCIPdebugMsg(scip, "error parsing conjunctive constraint: \"%s\"\n", str);
584  *success = FALSE;
585  goto TERMINATE;
586  }
587  }
588 
589  saveptr = strpbrk(saveptr, "(,");
590  }
591  while( saveptr != NULL && *saveptr == '(' );
592  }
593 
594  /* we found a ',' so the end of the first sub-constraint is determined */
595  if( saveptr != NULL )
596  {
597  assert(*saveptr == ',');
598 
599  /* resize constraint array if necessary */
600  if( nconss == sconss )
601  {
602  sconss = SCIPcalcMemGrowSize(scip, nconss+1);
603  assert(nconss < sconss);
604 
605  SCIP_CALL( SCIPreallocBufferArray(scip, &conss, sconss) );
606  }
607  assert(nexttokenstart != NULL); /* for lint */
608  assert(saveptr > nexttokenstart);
609 
610  /* extract token for parsing */
611  SCIP_CALL( SCIPduplicateBufferArray(scip, &token, nexttokenstart, saveptr - nexttokenstart + 1) );
612  token[saveptr - nexttokenstart] = '\0';
613 
614  SCIPdebugMsg(scip, "conjunctive parsing token(constraint): %s\n", token);
615 
616  /* parsing a constraint, part of the conjunction */
617  SCIP_CALL( SCIPparseCons(scip, &(conss[nconss]), token, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, success) );
618 
619  SCIPfreeBufferArray(scip, &token);
620 
621  if( *success )
622  ++nconss;
623  else
624  {
625  SCIPdebugMsg(scip, "error parsing conjunctive constraint: \"%s\"\n", str);
626  goto TERMINATE;
627  }
628  /* skip ',' delimeter */
629  ++saveptr;
630  /* remember token start position */
631  nexttokenstart = saveptr;
632 
633  saveptr = strpbrk(saveptr, "(,");
634  }
635  }
636  while( saveptr != NULL );
637  }
638 
639  /* find end of conjunction constraint */
640  saveptr = strrchr(nexttokenstart, ')');
641 
642  if( saveptr == NULL )
643  {
644  SCIPdebugMsg(scip, "error parsing conjunctive constraint: \"%s\"\n", str);
645  *success = FALSE;
646  goto TERMINATE;
647  }
648  /* parse last sub-constraint */
649  else
650  {
651  /* resize constraint array if necessary */
652  if( nconss == sconss )
653  {
654  ++sconss;
655  SCIP_CALL( SCIPreallocBufferArray(scip, &conss, sconss) );
656  }
657 
658  assert(saveptr > nexttokenstart);
659 
660  /* extract token for parsing */
661  SCIP_CALL( SCIPduplicateBufferArray(scip, &token, nexttokenstart, saveptr - nexttokenstart + 1) );
662  token[saveptr - nexttokenstart] = '\0';
663 
664  SCIPdebugMsg(scip, "conjunctive parsing token(constraint): %s\n", token);
665 
666  /* parsing a constraint, part of the conjunction */
667  SCIP_CALL( SCIPparseCons(scip, &(conss[nconss]), token, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, success) );
668 
669  if( *success )
670  ++nconss;
671 
672  SCIPfreeBufferArray(scip, &token);
673  }
674  assert(nconss > 0 || !(*success));
675 
676  /* if parsing sub-constraints was fine, create the conjunctive constraint */
677  if( *success )
678  {
679  /* create conjunctive constraint */
680  SCIP_CALL( SCIPcreateConsConjunction(scip, cons, name, nconss, conss,
681  enforce, check, local, modifiable, dynamic) );
682  }
683 
684  /* free parsed constraints */
685  for( --nconss; nconss >= 0; --nconss )
686  {
687  SCIP_CALL( SCIPreleaseCons(scip, &conss[nconss]) );
688  }
689 
690  TERMINATE:
691  /* free temporary memory */
692  SCIPfreeBufferArray(scip, &copystr);
693  SCIPfreeBufferArray(scip, &conss);
694 
695  return SCIP_OKAY;
696 }
697 
698 /** constraint copying method of constraint handler */
699 static
700 SCIP_DECL_CONSCOPY(consCopyConjunction)
701 { /*lint --e{715}*/
702  SCIP_CONSDATA* sourcedata;
703  SCIP_CONS** sourceconss;
704  SCIP_CONS** conss;
705  int nconss;
706  int c;
707 
708  *valid = TRUE;
709 
710  sourcedata = SCIPconsGetData(sourcecons);
711  assert(sourcedata != NULL);
712 
713  sourceconss = sourcedata->conss;
714  nconss = sourcedata->nconss;
715 
716  if( nconss > 0 )
717  {
718  assert(sourceconss != NULL);
719 
720  SCIP_CALL( SCIPallocBufferArray(scip, &conss, nconss) );
721 
722  /* copy each constraint one by one */
723  for( c = 0; c < nconss && (*valid); ++c )
724  {
725  SCIP_CALL( SCIPgetConsCopy(sourcescip, scip, sourceconss[c], &conss[c], SCIPconsGetHdlr(sourceconss[c]),
726  varmap, consmap, SCIPconsGetName(sourceconss[c]),
727  SCIPconsIsInitial(sourceconss[c]), SCIPconsIsSeparated(sourceconss[c]), SCIPconsIsEnforced(sourceconss[c]),
728  SCIPconsIsChecked(sourceconss[c]), SCIPconsIsPropagated(sourceconss[c]),
729  SCIPconsIsLocal(sourceconss[c]), SCIPconsIsModifiable(sourceconss[c]),
730  SCIPconsIsDynamic(sourceconss[c]), SCIPconsIsRemovable(sourceconss[c]), SCIPconsIsStickingAtNode(sourceconss[c]),
731  global, valid) );
732  assert(!(*valid) || conss[c] != NULL);
733  }
734 
735  if( *valid )
736  {
737  if( name == NULL )
738  {
739  SCIP_CALL( SCIPcreateConsConjunction(scip, cons, SCIPconsGetName(sourcecons), nconss, conss,
740  enforce, check, local, modifiable, dynamic) );
741  }
742  else
743  {
744  SCIP_CALL( SCIPcreateConsConjunction(scip, cons, name, nconss, conss,
745  enforce, check, local, modifiable, dynamic) );
746  }
747  }
748 
749  /* release the copied constraints */
750  for( c = (*valid ? c - 1 : c - 2); c >= 0; --c )
751  {
752  assert(conss[c] != NULL);
753  SCIP_CALL( SCIPreleaseCons(scip, &conss[c]) );
754  }
755 
756  SCIPfreeBufferArray(scip, &conss);
757  }
758 
759  return SCIP_OKAY;
760 }
761 
762 
763 /*
764  * constraint specific interface methods
765  */
766 
767 /** creates the handler for conjunction constraints and includes it in SCIP */
769  SCIP* scip /**< SCIP data structure */
770  )
771 {
772  SCIP_CONSHDLR* conshdlr;
773 
774  /* include constraint handler */
777  consEnfolpConjunction, consEnfopsConjunction, consCheckConjunction, consLockConjunction,
778  NULL) );
779 
780  assert(conshdlr != NULL);
781 
782  /* set non-fundamental callbacks via specific setter functions */
783  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyConjunction, consCopyConjunction) );
784  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteConjunction) );
785  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseConjunction) );
786  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolConjunction, CONSHDLR_MAXPREROUNDS,
788  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintConjunction) );
789  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransConjunction) );
790  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxConjunction) );
791 
792  return SCIP_OKAY;
793 }
794 
795 /** creates and captures a conjunction constraint
796  *
797  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
798  */
800  SCIP* scip, /**< SCIP data structure */
801  SCIP_CONS** cons, /**< pointer to hold the created constraint */
802  const char* name, /**< name of constraint */
803  int nconss, /**< number of initial constraints in conjunction */
804  SCIP_CONS** conss, /**< initial constraint in conjunction */
805  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
806  * TRUE for model constraints, FALSE for additional, redundant constraints. */
807  SCIP_Bool check, /**< should the constraint be checked for feasibility?
808  * TRUE for model constraints, FALSE for additional, redundant constraints. */
809  SCIP_Bool local, /**< is constraint only valid locally?
810  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
811  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
812  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
813  * adds coefficients to this constraint. */
814  SCIP_Bool dynamic /**< is constraint subject to aging?
815  * Usually set to FALSE. Set to TRUE for own cuts which
816  * are separated as constraints. */
817  )
818 {
819  SCIP_CONSHDLR* conshdlr;
820  SCIP_CONSDATA* consdata;
821 
822  /* find the conjunction constraint handler */
823  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
824  if( conshdlr == NULL )
825  {
826  SCIPerrorMessage("conjunction constraint handler not found\n");
827  return SCIP_PLUGINNOTFOUND;
828  }
829 
830  /* create constraint data */
831  SCIP_CALL( consdataCreate(scip, &consdata, conss, nconss) );
832 
833  /* create constraint */
834  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, FALSE, FALSE, enforce, check, FALSE,
835  local, modifiable, dynamic, FALSE, FALSE) );
836 
837  return SCIP_OKAY;
838 }
839 
840 /** creates and captures an and constraint
841  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
842  * method SCIPcreateConsConjunction(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
843  *
844  * @see SCIPcreateConsConjunction() for information about the basic constraint flag configuration
845  *
846  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
847  */
849  SCIP* scip, /**< SCIP data structure */
850  SCIP_CONS** cons, /**< pointer to hold the created constraint */
851  const char* name, /**< name of constraint */
852  int nconss, /**< number of initial constraints in conjunction */
853  SCIP_CONS** conss /**< initial constraint in conjunction */
854  )
855 {
856  assert(scip != NULL);
857 
858  SCIP_CALL( SCIPcreateConsConjunction(scip, cons, name, nconss, conss,
859  TRUE, TRUE, FALSE, FALSE, FALSE) );
860 
861  return SCIP_OKAY;
862 }
863 
864 /** adds constraint to the conjunction of constraints */
866  SCIP* scip, /**< SCIP data structure */
867  SCIP_CONS* cons, /**< conjunction constraint */
868  SCIP_CONS* addcons /**< additional constraint in conjunction */
869  )
870 {
871  SCIP_CONSDATA* consdata;
872 
873  assert(cons != NULL);
874  assert(addcons != NULL);
875 
876  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
877  {
878  SCIPerrorMessage("constraint is not a conjunction constraint\n");
879  return SCIP_INVALIDDATA;
880  }
881 
882  consdata = SCIPconsGetData(cons);
883  assert(consdata != NULL);
884 
885  SCIP_CALL( consdataAddCons(scip, consdata, addcons) );
886 
887  return SCIP_OKAY;
888 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip_cons.c:586
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:80
SCIP_RETCODE SCIPparseCons(SCIP *scip, SCIP_CONS **cons, const char *str, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool *success)
Definition: scip_cons.c:1018
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:877
static SCIP_DECL_CONSPARSE(consParseConjunction)
#define CONSHDLR_DESC
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip_cons.c:934
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8316
public methods for memory management
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip_cons.c:308
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8276
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip_cons.c:166
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:770
SCIP_RETCODE SCIPgetConsCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_CONS *sourcecons, SCIP_CONS **targetcons, SCIP_CONSHDLR *sourceconshdlr, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *name, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool global, SCIP_Bool *valid)
Definition: scip_copy.c:1534
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8138
#define FALSE
Definition: def.h:73
SCIP_RETCODE SCIPaddConsLocksType(SCIP *scip, SCIP_CONS *cons, SCIP_LOCKTYPE locktype, int nlockspos, int nlocksneg)
Definition: scip_cons.c:2009
#define TRUE
Definition: def.h:72
#define SCIPdebug(x)
Definition: pub_message.h:84
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3468
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8246
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:563
static SCIP_RETCODE checkAllConss(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_SOL *sol, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool completely, SCIP_RESULT *result)
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:95
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_CONS **conss, int nconss)
static SCIP_DECL_CONSCOPY(consCopyConjunction)
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:119
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip_cons.c:525
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:123
#define CONSHDLR_ENFOPRIORITY
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:78
static SCIP_DECL_CONSLOCK(consLockConjunction)
#define SCIPdebugMsg
Definition: scip_message.h:69
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:559
SCIP_RETCODE SCIPincludeConshdlrConjunction(SCIP *scip)
void SCIPupdateSolConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip_sol.c:265
#define CONSHDLR_NAME
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2837
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
#define CONSHDLR_EAGERFREQ
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:92
public methods for managing constraints
SCIP_RETCODE SCIPcheckCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_RESULT *result)
Definition: scip_cons.c:2072
static SCIP_DECL_CONSCHECK(consCheckConjunction)
constraint handler for conjunction constraints
#define SCIPerrorMessage
Definition: pub_message.h:55
static SCIP_RETCODE consdataAddCons(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_CONS *cons)
#define NULL
Definition: lpi_spx1.cpp:155
public methods for problem copies
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8107
#define SCIP_CALL(x)
Definition: def.h:370
#define SCIPensureBlockMemoryArray(scip, ptr, arraysizeptr, minsize)
Definition: scip_mem.h:94
static SCIP_DECL_CONSENFOLP(consEnfolpConjunction)
SCIP_RETCODE SCIPaddConsElemConjunction(SCIP *scip, SCIP_CONS *cons, SCIP_CONS *addcons)
#define CONSHDLR_PRESOLTIMING
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:56
SCIP_RETCODE SCIPcaptureCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1075
public methods for constraint handler plugins and constraints
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8346
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:111
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:130
#define SCIP_Bool
Definition: def.h:70
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip_cons.c:332
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2473
static SCIP_DECL_CONSENFORELAX(consEnforelaxConjunction)
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8256
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8336
static SCIP_DECL_CONSPRINT(consPrintConjunction)
#define CONSHDLR_CHECKPRIORITY
static SCIP_DECL_CONSDELETE(consDeleteConjunction)
general public methods
public methods for solutions
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8266
static SCIP_DECL_CONSENFOPS(consEnfopsConjunction)
static SCIP_DECL_CONSTRANS(consTransConjunction)
SCIP_RETCODE SCIPtransformConss(SCIP *scip, int nconss, SCIP_CONS **conss, SCIP_CONS **transconss)
Definition: scip_cons.c:1562
public methods for message output
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyConjunction)
static SCIP_DECL_CONSPRESOL(consPresolConjunction)
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8077
#define CONSHDLR_MAXPREROUNDS
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8097
public methods for message handling
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8356
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4167
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2764
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:98
SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip_prob.c:3387
SCIP_RETCODE SCIPcreateConsConjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nconss, SCIP_CONS **conss, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:199
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1110
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip_cons.c:793
public methods for global and local (sub)problems
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8296
SCIP_RETCODE SCIPcreateConsBasicConjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nconss, SCIP_CONS **conss)
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8326
#define CONSHDLR_NEEDSCONS
SCIP_RETCODE SCIPsetConsChecked(SCIP *scip, SCIP_CONS *cons, SCIP_Bool check)
Definition: scip_cons.c:1283
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:115
static SCIP_RETCODE addAllConss(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_RESULT *result)
memory allocation routines
SCIP_RETCODE SCIPtransformCons(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **transcons)
Definition: scip_cons.c:1521