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