/** creates and captures an and constraint * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the * method SCIPcreateConsConjunction(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h * * @see SCIPcreateConsConjunction() for information about the basic constraint flag configuration * * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons() */ SCIP_RETCODE SCIPcreateConsBasicConjunction( SCIP* scip, /**< SCIP data structure */ SCIP_CONS** cons, /**< pointer to hold the created constraint */ const char* name, /**< name of constraint */ int nconss, /**< number of initial constraints in conjunction */ SCIP_CONS** conss /**< initial constraint in conjunction */ ) { assert(scip != NULL); SCIP_CALL( SCIPcreateConsConjunction(scip, cons, name, nconss, conss, TRUE, TRUE, FALSE, FALSE, FALSE) ); return SCIP_OKAY; }
/** constraint parsing method of constraint handler */ static SCIP_DECL_CONSPARSE(consParseConjunction) { /*lint --e{715}*/ SCIP_CONS** conss; int nconss; int sconss; char* token; char* saveptr; char* nexttokenstart; char* copystr; assert(scip != NULL); assert(conshdlr != NULL); assert(cons != NULL); assert(success != NULL); assert(str != NULL); assert(name != NULL); SCIPdebugMessage("parsing conjunction <%s>\n", name); *success = TRUE; /* allocate memory for constraint in conjunction, initial size is set to 10 */ nconss = 0; sconss = 10; SCIP_CALL( SCIPallocBufferArray(scip, &conss, sconss) ); SCIP_CALL( SCIPduplicateBufferArray(scip, ©str, str, (int)strlen(str)+1) ); /* find '(' at the beginning, string should start with 'conjunction(' */ saveptr = strpbrk(copystr, "("); /*lint !e158*/ if( saveptr == NULL ) { SCIPdebugMessage("error parsing conjunctive constraint: \"%s\"\n", str); *success = FALSE; goto TERMINATE; } /* skip '(' */ ++saveptr; /* remember token start position */ nexttokenstart = saveptr; /* brackets '(' and ')' can exist co we check for them and the constraint delimeter */ saveptr = strpbrk(saveptr, "(,"); /* brackets '(' and ')' can exist in the rest of the string so we need to skip them to find the end of the first * sub-constraint marked by a ',' */ if( saveptr != NULL ) { do { int bracketcounter = 0; if( *saveptr == '(' ) { do { ++bracketcounter; ++saveptr; /* find last ending bracket */ while( bracketcounter > 0 ) { saveptr = strpbrk(saveptr, "()"); if( saveptr != NULL ) { if( *saveptr == '(' ) ++bracketcounter; else --bracketcounter; ++saveptr; } else { SCIPdebugMessage("error parsing conjunctive constraint: \"%s\"\n", str); *success = FALSE; goto TERMINATE; } } saveptr = strpbrk(saveptr, "(,"); } while( saveptr != NULL && *saveptr == '(' ); } /* we found a ',' so the end of the first sub-constraint is determined */ if( saveptr != NULL ) { assert(*saveptr == ','); /* resize constraint array if necessary */ if( nconss == sconss ) { sconss = SCIPcalcMemGrowSize(scip, nconss+1); assert(nconss < sconss); SCIP_CALL( SCIPreallocBufferArray(scip, &conss, sconss) ); } assert(saveptr > nexttokenstart); /* extract token for parsing */ SCIP_CALL( SCIPduplicateBufferArray(scip, &token, nexttokenstart, saveptr - nexttokenstart + 1) ); token[saveptr - nexttokenstart] = '\0'; SCIPdebugMessage("conjunctive parsing token(constraint): %s\n", token); /* parsing a constraint, part of the conjunction */ SCIP_CALL( SCIPparseCons(scip, &(conss[nconss]), token, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, success) ); SCIPfreeBufferArray(scip, &token); if( *success ) ++nconss; else { SCIPdebugMessage("error parsing conjunctive constraint: \"%s\"\n", str); goto TERMINATE; } /* skip ',' delimeter */ ++saveptr; /* remember token start position */ nexttokenstart = saveptr; saveptr = strpbrk(saveptr, "(,"); } } while( saveptr != NULL ); } /* find end of conjunction constraint */ saveptr = strrchr(nexttokenstart, ')'); if( saveptr == NULL ) { SCIPdebugMessage("error parsing conjunctive constraint: \"%s\"\n", str); *success = FALSE; goto TERMINATE; } /* parse last sub-constraint */ else { /* resize constraint array if necessary */ if( nconss == sconss ) { ++sconss; SCIP_CALL( SCIPreallocBufferArray(scip, &conss, sconss) ); } assert(saveptr > nexttokenstart); /* extract token for parsing */ SCIP_CALL( SCIPduplicateBufferArray(scip, &token, nexttokenstart, saveptr - nexttokenstart + 1) ); token[saveptr - nexttokenstart] = '\0'; SCIPdebugMessage("conjunctive parsing token(constraint): %s\n", token); /* parsing a constraint, part of the conjunction */ SCIP_CALL( SCIPparseCons(scip, &(conss[nconss]), token, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, success) ); if( *success ) ++nconss; SCIPfreeBufferArray(scip, &token); } assert(nconss > 0 || !(*success)); /* if parsing sub-constraints was fine, create the conjunctive constraint */ if( *success ) { /* create conjunctive constraint */ SCIP_CALL( SCIPcreateConsConjunction(scip, cons, name, nconss, conss, enforce, check, local, modifiable, dynamic) ); } /* free parsed constraints */ for( --nconss; nconss >= 0; --nconss ) { SCIP_CALL( SCIPreleaseCons(scip, &conss[nconss]) ); } TERMINATE: /* free temporary memory */ SCIPfreeBufferArray(scip, ©str); SCIPfreeBufferArray(scip, &conss); return SCIP_OKAY; }
/** constraint copying method of constraint handler */ static SCIP_DECL_CONSCOPY(consCopyConjunction) { /*lint --e{715}*/ SCIP_CONSDATA* sourcedata; SCIP_CONS** sourceconss; SCIP_CONS** conss; int nconss; int c; *valid = TRUE; sourcedata = SCIPconsGetData(sourcecons); assert(sourcedata != NULL); sourceconss = sourcedata->conss; nconss = sourcedata->nconss; if( nconss > 0 ) { assert(sourceconss != NULL); SCIP_CALL( SCIPallocBufferArray(scip, &conss, nconss) ); /* copy each constraint one by one */ for( c = 0; c < nconss && (*valid); ++c ) { SCIP_CALL( SCIPgetConsCopy(sourcescip, scip, sourceconss[c], &conss[c], SCIPconsGetHdlr(sourceconss[c]), varmap, consmap, SCIPconsGetName(sourceconss[c]), SCIPconsIsInitial(sourceconss[c]), SCIPconsIsSeparated(sourceconss[c]), SCIPconsIsEnforced(sourceconss[c]), SCIPconsIsChecked(sourceconss[c]), SCIPconsIsPropagated(sourceconss[c]), SCIPconsIsLocal(sourceconss[c]), SCIPconsIsModifiable(sourceconss[c]), SCIPconsIsDynamic(sourceconss[c]), SCIPconsIsRemovable(sourceconss[c]), SCIPconsIsStickingAtNode(sourceconss[c]), global, valid) ); assert(!(*valid) || conss[c] != NULL); } if( *valid ) { if( name == NULL ) { SCIP_CALL( SCIPcreateConsConjunction(scip, cons, SCIPconsGetName(sourcecons), nconss, conss, enforce, check, local, modifiable, dynamic) ); } else { SCIP_CALL( SCIPcreateConsConjunction(scip, cons, name, nconss, conss, enforce, check, local, modifiable, dynamic) ); } } /* release the copied constraints */ for( c = (*valid ? c - 1 : c - 2); c >= 0; --c ) { assert(conss[c] != NULL); SCIP_CALL( SCIPreleaseCons(scip, &conss[c]) ); } SCIPfreeBufferArray(scip, &conss); } return SCIP_OKAY; }