From a29bc804c365049c8f3b1f00849831ba2b876382 Mon Sep 17 00:00:00 2001 From: Dominik Kamp Date: Fri, 13 Sep 2024 10:59:20 +0200 Subject: [PATCH] Fix pseudoboolean handling --- CHANGELOG | 3 + src/scip/cons_pseudoboolean.c | 1518 ++++++++++++++------------------- src/scip/reader_opb.c | 1288 +++++++++++----------------- 3 files changed, 1152 insertions(+), 1657 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 06422408a4..8f2565bb7c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -31,6 +31,9 @@ Fixed bugs - fixed that some variable type changes were not accounted correctly in presolve of linear constraints - fix constraint sorting in setpp-orbitope upgrade in symmetry code - fixed that SCIPnodeGetConsProps() also counted bound changes from propagators +- use original and-constraints of an untransformed pseudoboolean constraint when copying original problems to avert segmentation faults +- sort and-constraints of a pseudoboolean constraint with respect to the resultant problem indices to avoid shuffled copies +- treat pseudoboolean constraints as nonlinear constraints in OPB reader to prevent duplication mistakes Performance improvements ------------------------ diff --git a/src/scip/cons_pseudoboolean.c b/src/scip/cons_pseudoboolean.c index 10e73c1143..69383c8193 100644 --- a/src/scip/cons_pseudoboolean.c +++ b/src/scip/cons_pseudoboolean.c @@ -28,7 +28,7 @@ * @author Gerald Gamrath * @author Stefan Heinz * @author Michael Winkler - * + * @author Dominik Kamp * * The constraint handler deals with pseudo Boolean constraints. These are constraints of the form * \f[ @@ -179,7 +179,7 @@ struct SCIP_ConsData SCIP_LINEARCONSTYPE linconstype; /**< type of linear constraint which represents this pseudoboolean constraint */ int nlinvars; /**< number of linear variables (without and-resultants) */ - CONSANDDATA** consanddatas; /**< array of and-constraints-data-objects sorted after index of + CONSANDDATA** consanddatas; /**< array of and-constraints-data-objects sorted after problem index of * and-resultant of corresponding and-constraint */ SCIP_Real* andcoefs; /**< array of coefficients for and-constraints of * and-constraints-data-objects @@ -229,74 +229,79 @@ struct SCIP_ConshdlrData int noriguses; /**< how many consanddata objects are used by original constraints */ }; + /* * Local methods */ +/** comparison method for sorting and-resultants according to their problem index, which is used instead of the + * original index because the implicit resultants are shuffled when creating the constraints that otherwise results in + * shuffled problem copies, + * if an and-resultant is deleted, it will be put in front with respect to its original index while sorting + */ +static +SCIP_DECL_SORTPTRCOMP(resvarComp) +{ + int varind1 = SCIPvarGetProbindex((SCIP_VAR*)elem1); + int varind2 = SCIPvarGetProbindex((SCIP_VAR*)elem2); + + if( varind1 < varind2 ) + return -1; + else if( varind1 > varind2 ) + return +1; + else if( varind1 != -1 ) + { + assert(elem1 == elem2); + return 0; + } + + return SCIPvarComp(elem1, elem2); +} -/** comparison method for sorting consanddatas according to the index of their corresponding resultant variables, if a - * consanddata object is delete it is handled like it has an inactive resultant, so this will be put in front while - * sorting +/** comparison method for sorting consanddatas according to the problem index of their corresponding and-resultants, + * if a consanddata object is deleted, it is handled like it has an inactive resultant, so this will be put + * in front while sorting */ static SCIP_DECL_SORTPTRCOMP(resvarCompWithInactive) { - CONSANDDATA* consanddata1; - CONSANDDATA* consanddata2; + CONSANDDATA* consanddata1 = (CONSANDDATA*)elem1; + CONSANDDATA* consanddata2 = (CONSANDDATA*)elem2; - consanddata1 = (CONSANDDATA*)elem1; - consanddata2 = (CONSANDDATA*)elem2; + assert(consanddata1 != NULL); + assert(consanddata2 != NULL); - /* check if and constraint data object is still valid */ - if( !consanddata1->istransformed ) + /* consider that constraint data object can be only original */ + if( consanddata1->istransformed != consanddata2->istransformed ) + return consanddata1->istransformed ? +1 : -1; + + SCIP_CONS* consand1; + SCIP_CONS* consand2; + + if( consanddata1->istransformed ) { - if( !consanddata2->istransformed ) - { - return 0; - } - else - return -1; + consand1 = consanddata1->cons; + consand2 = consanddata2->cons; + } + else + { + consand1 = consanddata1->origcons; + consand2 = consanddata2->origcons; } - else if( !consanddata2->istransformed ) - return +1; - - assert(consanddata1->cons != NULL); - assert(consanddata2->cons != NULL); - /* check if and constraint is still active */ - if( SCIPconsIsDeleted(consanddata1->cons) ) + /* check if and-constraint is still active */ + if( SCIPconsIsDeleted(consand1) ) { - if( SCIPconsIsDeleted(consanddata2->cons) ) - { + if( SCIPconsIsDeleted(consand2) ) return 0; - } else return -1; } - else if( SCIPconsIsDeleted(consanddata2->cons) ) + else if( SCIPconsIsDeleted(consand2) ) return +1; - else - { - SCIP_VAR* var1; - SCIP_VAR* var2; - - /* hack with setting the first pointer to NULL */ - var1 = SCIPgetResultantAnd(NULL, consanddata1->cons); - var2 = SCIPgetResultantAnd(NULL, consanddata2->cons); - assert(var1 != NULL); - assert(var2 != NULL); - - if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) ) - return -1; - else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) ) - return +1; - else - { - assert(var1 == var2); - return 0; - } - } + /* hack with setting the scip pointer to NULL */ + return resvarComp((void*)SCIPgetResultantAnd(NULL, consand1), (void*)SCIPgetResultantAnd(NULL, consand2)); } /** gets the key of the given element */ @@ -619,7 +624,7 @@ SCIP_RETCODE getLinearConsVarsData( SCIP*const scip, /**< SCIP data structure */ SCIP_CONS*const cons, /**< linear constraint */ SCIP_LINEARCONSTYPE const constype, /**< linear constraint type */ - SCIP_VAR**const vars, /**< array to store sorted (after indices) variables of linear constraint */ + SCIP_VAR**const vars, /**< array to store variables of linear constraint */ SCIP_Real*const coefs, /**< array to store coefficient of linear constraint, or NULL */ int*const nvars /**< pointer to store number variables of linear constraint */ ) @@ -713,16 +718,16 @@ SCIP_RETCODE getLinearConsVarsData( if( coefs != NULL ) { - for( v = 0; v < *nvars; ++v ) - { - vars[v] = linvars[v]; - coefs[v] = 1.0; - } + for( v = 0; v < *nvars; ++v ) + { + vars[v] = linvars[v]; + coefs[v] = 1.0; + } } else { - for( v = 0; v < *nvars; ++v ) - vars[v] = linvars[v]; + for( v = 0; v < *nvars; ++v ) + vars[v] = linvars[v]; } break; @@ -737,18 +742,18 @@ SCIP_RETCODE getLinearConsVarsData( if( coefs != NULL ) { - weights = SCIPgetWeightsEQKnapsack(scip, cons); + weights = SCIPgetWeightsEQKnapsack(scip, cons); - for( v = 0; v < *nvars; ++v ) - { - vars[v] = linvars[v]; - coefs[v] = (SCIP_Real) weights[v]; - } + for( v = 0; v < *nvars; ++v ) + { + vars[v] = linvars[v]; + coefs[v] = (SCIP_Real) weights[v]; + } } else { - for( v = 0; v < *nvars; ++v ) - vars[v] = linvars[v]; + for( v = 0; v < *nvars; ++v ) + vars[v] = linvars[v]; } break; @@ -760,23 +765,10 @@ SCIP_RETCODE getLinearConsVarsData( return SCIP_INVALIDDATA; } - /* sort variables after indices */ - if( coefs != NULL ) - { - SCIPsortPtrReal((void**)vars, coefs, SCIPvarComp, *nvars); - } - else - { - SCIPsortPtr((void**)vars, SCIPvarComp, *nvars); - } - return SCIP_OKAY; } -/** calculate all not artificial linear variables and all artificial and-resultants which will be ordered like the - * 'consanddatas' such that the and-resultant of the and-constraint is the and-resultant in the 'andress' array - * afterwards - */ +/** splits up into original linear variables and artificial and-resultants */ static SCIP_RETCODE getLinVarsAndAndRess( SCIP*const scip, /**< SCIP data structure */ @@ -820,16 +812,6 @@ SCIP_RETCODE getLinVarsAndAndRess( assert(conshdlrdata != NULL); assert(conshdlrdata->hashmap != NULL); - /* @note it is necessary that the linear constraint is merged (not needed for negated variables) and sorted after - * indices - */ - -#ifndef NDEBUG - /* check that old variables are sorted */ - for( v = nvars - 1; v > 0; --v ) - assert(SCIPvarGetIndex(vars[v]) >= SCIPvarGetIndex(vars[v - 1])); -#endif - /* split variables into original and artificial variables */ for( v = 0; v < nvars; ++v ) { @@ -853,29 +835,29 @@ SCIP_RETCODE getLinVarsAndAndRess( */ if( hashmapentryexists ) { - if( !SCIPconsIsOriginal(cons) ) - { + if( !SCIPconsIsOriginal(cons) ) + { CONSANDDATA* consanddata = (CONSANDDATA*) SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)(hashmapvar)); assert(consanddata != NULL); - hashmapentryexists = (consanddata->istransformed); + hashmapentryexists = (consanddata->istransformed); - if( hashmapentryexists ) - { - assert(consanddata->cons != NULL); - hashmapentryexists = !SCIPconsIsDeleted(consanddata->cons); - } - } + if( hashmapentryexists ) + { + assert(consanddata->cons != NULL); + hashmapentryexists = !SCIPconsIsDeleted(consanddata->cons); + } + } } if( !hashmapentryexists && linvars != NULL && nlinvars != NULL ) { linvars[*nlinvars] = vars[v]; - if( lincoefs != NULL ) - { - assert(coefs != NULL); - lincoefs[*nlinvars] = coefs[v]; - } + if( lincoefs != NULL ) + { + assert(coefs != NULL); + lincoefs[*nlinvars] = coefs[v]; + } ++(*nlinvars); } else if( hashmapentryexists && nandress != NULL ) @@ -896,21 +878,6 @@ SCIP_RETCODE getLinVarsAndAndRess( } } - /* @todo try to avoid sorting here */ - if( andress != NULL && nandress != NULL ) - { - /* sort and resultants by their variable index */ - if( andcoefs != NULL ) - { - assert(andnegs != NULL); - SCIPsortPtrRealBool((void**)andress, andcoefs, andnegs, SCIPvarComp, *nandress); - } - else - { - SCIPsortPtr((void**)andress, SCIPvarComp, *nandress); - } - } - return SCIP_OKAY; } @@ -1372,8 +1339,8 @@ SCIP_RETCODE consdataCreate( } } - /* sort and-constraints after indices of corresponding and-resultants */ - SCIPsortPtrPtrRealBool((void**)andress, (void**)((*consdata)->consanddatas), (*consdata)->andcoefs, (*consdata)->andnegs, SCIPvarComp, nandconss); + /* sort and-constraints after problem indices of corresponding and-resultants */ + SCIPsortPtrPtrRealBool((void**)andress, (void**)((*consdata)->consanddatas), (*consdata)->andcoefs, (*consdata)->andnegs, resvarComp, nandconss); /* free temporary memory */ SCIPfreeBufferArray(scip, &andress); @@ -1808,24 +1775,13 @@ SCIP_RETCODE consdataPrint( SCIP_CONSHDLR* conshdlr; SCIP_CONSHDLRDATA* conshdlrdata; SCIP_CONSDATA* consdata; - SCIP_VAR** vars; SCIP_Real* coefs; - int nvars; SCIP_Real lhs; SCIP_Real rhs; - - SCIP_VAR** linvars; - SCIP_Real* lincoefs; - int nlinvars; - int v; - - SCIP_VAR** andress; - SCIP_Real* andcoefs; - SCIP_Bool* andnegs; - int nandress; - SCIP_Bool printed; + int nvars; + int v; assert(scip != NULL); assert(cons != NULL); @@ -1847,11 +1803,6 @@ SCIP_RETCODE consdataPrint( /* allocate temporary memory */ SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) ); SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) ); - SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nvars) ); - SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nvars) ); - SCIP_CALL( SCIPallocBufferArray(scip, &andress, nvars) ); - SCIP_CALL( SCIPallocBufferArray(scip, &andcoefs, nvars) ); - SCIP_CALL( SCIPallocBufferArray(scip, &andnegs, nvars) ); /* get sides of linear constraint */ SCIP_CALL( getLinearConsSides(scip, consdata->lincons, consdata->linconstype, &lhs, &rhs) ); @@ -1863,14 +1814,6 @@ SCIP_RETCODE consdataPrint( SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) ); assert(nvars == 0 || (coefs != NULL)); - /* calculate all not artificial linear variables and all artificial and-resultants which will be ordered like the - * 'consanddatas' such that the and-resultant of the and-constraint is the and-resultant in the 'andress' array - * afterwards - */ - SCIP_CALL( getLinVarsAndAndRess(scip, cons, vars, coefs, nvars, linvars, lincoefs, &nlinvars, - andress, andcoefs, andnegs, &nandress) ); - assert(consdata->nconsanddatas == nandress); - /* number of variables should be consistent, number of 'real' linear variables plus number of and-constraints should * have to be equal to the number of variables in the linear constraint */ @@ -1880,76 +1823,113 @@ SCIP_RETCODE consdataPrint( if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) && !SCIPisEQ(scip, lhs, rhs) ) SCIPinfoMessage(scip, file, "%.15g <= ", lhs); - printed = FALSE; - - /* print coefficients and variables */ - if( nlinvars > 0) - { - printed= TRUE; - - /* print linear part of constraint */ - SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, linvars, lincoefs, nlinvars, TRUE) ); - } - conshdlr = SCIPconsGetHdlr(cons); assert(conshdlr != NULL); + conshdlrdata = SCIPconshdlrGetData(conshdlr); assert(conshdlrdata != NULL); assert(conshdlrdata->hashmap != NULL); - /* print all non-linear terms */ - for( v = nandress - 1; v >= 0; --v ) + printed = FALSE; + + /* print all terms */ + for( v = 0; v < nvars; ++v ) { - CONSANDDATA* consanddata; - SCIP_CONS* andcons; - SCIP_VAR** andvars; - int nandvars; + CONSANDDATA* consanddata = NULL; + SCIP_VAR** andvars = NULL; + SCIP_VAR* var = vars[v]; + int nandvars = 0; + + assert(SCIPvarIsBinary(var)); if( !SCIPconsIsOriginal(cons) ) { /* if the and resultant was fixed we print a constant */ - if( SCIPvarGetLbLocal(andress[v]) > 0.5 || SCIPvarGetUbLocal(andress[v]) < 0.5 ) + if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED ) { - if( SCIPvarGetLbGlobal(andress[v]) > 0.5 ) + if( SCIPvarGetLbGlobal(var) > 0.5 ) { printed = TRUE; - SCIPinfoMessage(scip, file, " %+.15g ", andcoefs[v] * SCIPvarGetLbGlobal(andress[v])); + SCIPinfoMessage(scip, file, " %+.15g ", coefs[v]); } continue; } - else if( SCIPvarGetStatus(andress[v]) == SCIP_VARSTATUS_AGGREGATED ) + else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_AGGREGATED ) { SCIP_VAR* aggrvar; SCIP_Bool negated; - SCIP_CALL( SCIPgetBinvarRepresentative(scip, andress[v], &aggrvar, &negated) ); + SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &aggrvar, &negated) ); assert(aggrvar != NULL); assert(SCIPvarGetType(aggrvar) == SCIP_VARTYPE_BINARY); printed = TRUE; - SCIPinfoMessage(scip, file, " %+.15g %s<%s>[B]", andcoefs[v], negated ? "~" : "", SCIPvarGetName(aggrvar)); + SCIPinfoMessage(scip, file, " %+.15g %s<%s>[B]", coefs[v], negated ? "~" : "", SCIPvarGetName(aggrvar)); continue; } } - consanddata = (CONSANDDATA*) SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)andress[v]); - assert(consanddata != NULL); + /* find and-constraint to standard or negated and-resultant */ + do + { + consanddata = (CONSANDDATA*)SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)var); - if( SCIPconsIsOriginal(cons) ) - andcons = consanddata->origcons; + if( consanddata != NULL ) + { + SCIP_CONS* andcons; + + if( SCIPconsIsOriginal(cons) ) + andcons = consanddata->origcons; + else + andcons = consanddata->cons; + assert(andcons != NULL); + + andvars = SCIPgetVarsAnd(scip, andcons); + nandvars = SCIPgetNVarsAnd(scip, andcons); + assert(nandvars == 0 || andvars != NULL); + + break; + } + + if( var == vars[v] ) + var = SCIPvarGetNegatedVar(var); + else + var = vars[v]; + } + while( var != vars[v] ); + + /* print general coefficient */ + if( consanddata != NULL && nandvars == 0 ) + { + if( var == vars[v] ) + { + printed = TRUE; + SCIPinfoMessage(scip, file, " %+.15g ", coefs[v]); + } + continue; + } + else if( coefs[v] == 1.0 ) + { + if( v > 0 ) + SCIPinfoMessage(scip, file, " +"); + } + else if( coefs[v] == -1.0 ) + SCIPinfoMessage(scip, file, " -"); else - andcons = consanddata->cons; - assert(andcons != NULL); + SCIPinfoMessage(scip, file, " %+.15g", coefs[v]); - andvars = SCIPgetVarsAnd(scip, andcons); - nandvars = SCIPgetNVarsAnd(scip, andcons); - assert(nandvars == 0 || andvars != NULL); + printed = TRUE; - if( nandvars > 0 ) + /* print linear term */ + if( consanddata == NULL ) { - printed = TRUE; - SCIPinfoMessage(scip, file, " %+.15g %s(", andcoefs[v], andnegs[v] ? "~" : ""); + SCIP_CALL( SCIPwriteVarName(scip, file, var, TRUE) ); + } + /* print non-linear term */ + else + { + SCIPinfoMessage(scip, file, "%s(", var == vars[v] ? "" : "~"); /* @todo: better write new method SCIPwriteProduct */ /* print variable list */ @@ -1959,27 +1939,23 @@ SCIP_RETCODE consdataPrint( } } + /* print zero value */ if( !printed ) { SCIPinfoMessage(scip, file, " 0 "); } /* free temporary memory */ - SCIPfreeBufferArray(scip, &andnegs); - SCIPfreeBufferArray(scip, &andcoefs); - SCIPfreeBufferArray(scip, &andress); - SCIPfreeBufferArray(scip, &lincoefs); - SCIPfreeBufferArray(scip, &linvars); SCIPfreeBufferArray(scip, &coefs); SCIPfreeBufferArray(scip, &vars); /* print right hand side */ if( SCIPisEQ(scip, lhs, rhs) ) - SCIPinfoMessage(scip, file, "== %.15g", rhs); + SCIPinfoMessage(scip, file, " == %.15g", rhs); else if( !SCIPisInfinity(scip, rhs) ) - SCIPinfoMessage(scip, file, "<= %.15g", rhs); + SCIPinfoMessage(scip, file, " <= %.15g", rhs); else if( !SCIPisInfinity(scip, -lhs) ) - SCIPinfoMessage(scip, file, ">= %.15g", lhs); + SCIPinfoMessage(scip, file, " >= %.15g", lhs); else SCIPinfoMessage(scip, file, " [free]"); @@ -2448,10 +2424,7 @@ SCIP_RETCODE chgLhs( SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) ); assert(nvars == 0 || (coefs != NULL)); - /* calculate all not artificial linear variables and all artificial and-resultants which will be ordered like the - * 'consanddatas' such that the and-resultant of the and-constraint is the and-resultant in the 'andress' array - * afterwards - */ + /* calculate all not artificial linear variables and all artificial and-resultants */ SCIP_CALL( getLinVarsAndAndRess(scip, cons, vars, coefs, nvars, linvars, lincoefs, &nlinvars, andress, andcoefs, andnegs, &nandress) ); assert(consdata->nconsanddatas == nandress); @@ -2622,10 +2595,7 @@ SCIP_RETCODE chgRhs( SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) ); assert(nvars == 0 || (coefs != NULL)); - /* calculate all not artificial linear variables and all artificial and-resultants which will be ordered like the - * 'consanddatas' such that the and-resultant of the and-constraint is the and-resultant in the 'andress' array - * afterwards - */ + /* calculate all not artificial linear variables and all artificial and-resultants */ SCIP_CALL( getLinVarsAndAndRess(scip, cons, vars, coefs, nvars, linvars, lincoefs, &nlinvars, andress, andcoefs, andnegs, &nandress) ); assert(consdata->nconsanddatas == nandress); @@ -3027,8 +2997,8 @@ SCIP_RETCODE createAndAddLinearCons( /* free temporary memory */ SCIPfreeBufferArray(scip, &transvars); - *lhs = 1.0; - *rhs = SCIPinfinity(scip); + *lhs = 1.0; + *rhs = SCIPinfinity(scip); } upgrconshdlr = SCIPfindConshdlr(scip, "setppc"); @@ -3099,8 +3069,8 @@ SCIP_RETCODE createAndAddLinearCons( /* release temporary memory */ SCIPfreeBufferArray(scip, &transvars); - *lhs = 1.0; - *rhs = 1.0; + *lhs = 1.0; + *rhs = 1.0; } else if( (SCIPisInfinity(scip, -*lhs) && SCIPisEQ(scip, *rhs, 1.0 - ncoeffsnone)) || (SCIPisEQ(scip, *lhs, ncoeffspone - 1.0) && SCIPisInfinity(scip, *rhs)) ) @@ -3149,8 +3119,8 @@ SCIP_RETCODE createAndAddLinearCons( /* release temporary memory */ SCIPfreeBufferArray(scip, &transvars); - *lhs = -SCIPinfinity(scip); - *rhs = 1.0; + *lhs = -SCIPinfinity(scip); + *rhs = 1.0; } else if( (SCIPisEQ(scip, *lhs, 1.0 - ncoeffsnone) && SCIPisInfinity(scip, *rhs)) || (SCIPisInfinity(scip, -*lhs) && SCIPisEQ(scip, *rhs, ncoeffspone - 1.0)) ) @@ -3210,8 +3180,8 @@ SCIP_RETCODE createAndAddLinearCons( /* release temporary memory */ SCIPfreeBufferArray(scip, &transvars); - *lhs = 1.0; - *rhs = SCIPinfinity(scip); + *lhs = 1.0; + *rhs = SCIPinfinity(scip); } } @@ -3299,8 +3269,8 @@ SCIP_RETCODE createAndAddLinearCons( SCIPfreeBufferArray(scip, &weights); SCIPfreeBufferArray(scip, &transvars); - *lhs = -SCIPinfinity(scip); - *rhs = capacity; + *lhs = -SCIPinfinity(scip); + *rhs = capacity; } #ifdef WITHEQKNAPSACK @@ -3387,8 +3357,8 @@ SCIP_RETCODE createAndAddLinearCons( SCIPfreeBufferArray(scip, &weights); SCIPfreeBufferArray(scip, &transvars); - *lhs = capacity; - *rhs = capacity; + *lhs = capacity; + *rhs = capacity; } #endif } @@ -3446,23 +3416,11 @@ SCIP_RETCODE checkOrigPbCons( SCIP_VAR** vars; SCIP_Real* coefs; - int nvars; SCIP_Real lhs; SCIP_Real rhs; - - SCIP_VAR** linvars; - SCIP_Real* lincoefs; - int nlinvars; - int v; - - SCIP_VAR** andress; - SCIP_Real* andcoefs; - int nandress; - - SCIP_CONS* andcons; - SCIP_Real andvalue; SCIP_Real activity; - int c; + int nvars; + int v; SCIP_Real lhsviol; SCIP_Real rhsviol; @@ -3491,10 +3449,6 @@ SCIP_RETCODE checkOrigPbCons( /* allocate temporary memory */ SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) ); SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) ); - SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nvars) ); - SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nvars) ); - SCIP_CALL( SCIPallocBufferArray(scip, &andress, nvars) ); - SCIP_CALL( SCIPallocBufferArray(scip, &andcoefs, nvars) ); /* get sides of linear constraint */ SCIP_CALL( getLinearConsSides(scip, consdata->lincons, consdata->linconstype, &lhs, &rhs) ); @@ -3511,114 +3465,72 @@ SCIP_RETCODE checkOrigPbCons( */ assert(consdata->nlinvars + consdata->nconsanddatas == nvars); - nlinvars = 0; - conshdlr = SCIPconsGetHdlr(cons); assert(conshdlr != NULL); + conshdlrdata = SCIPconshdlrGetData(conshdlr); assert(conshdlrdata != NULL); assert(conshdlrdata->hashmap != NULL); - nandress = 0; - activity = 0.0; - /* split variables into original and artificial variables and compute activity on normal linear variables (without - * terms) - */ + /* compute pseudoboolean activity */ for( v = 0; v < nvars; ++v ) { - SCIP_VAR* hashmapvar; - SCIP_Bool negated; - - assert(vars[v] != NULL); - - /* negated variables can also exist in the original problem, so we need to check */ - if( !SCIPhashmapExists(conshdlrdata->hashmap, (void*)(vars[v])) && SCIPvarIsNegated(vars[v]) ) - { - hashmapvar = SCIPvarGetNegationVar(vars[v]); - negated = TRUE; - } - else - { - hashmapvar = vars[v]; - negated = FALSE; - } - assert(hashmapvar != NULL); + CONSANDDATA* consanddata = NULL; + SCIP_VAR* var = vars[v]; + SCIP_Real solval; - if( !SCIPhashmapExists(conshdlrdata->hashmap, (void*)(hashmapvar)) ) + /* find and-constraint to standard or negated and-resultant */ + do { - assert(!SCIPhashmapExists(conshdlrdata->hashmap, (void*)(vars[v]))); + consanddata = (CONSANDDATA*)SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)var); - activity += coefs[v] * SCIPgetSolVal(scip, sol, vars[v]); + if( consanddata != NULL ) + break; - linvars[nlinvars] = vars[v]; - lincoefs[nlinvars] = coefs[v]; - ++nlinvars; - } - else - { - /* negate coefficient in case of an original negated variable */ - andress[nandress] = hashmapvar; - if( negated ) - { - if( !SCIPisInfinity(scip, -lhs) ) - lhs -= coefs[v]; - if( !SCIPisInfinity(scip, rhs) ) - rhs -= coefs[v]; - andcoefs[nandress] = -coefs[v]; - } + if( var == vars[v] ) + var = SCIPvarGetNegatedVar(var); else - andcoefs[nandress] = coefs[v]; - ++nandress; + var = vars[v]; } - } - assert(nandress == consdata->nconsanddatas); + while( var != vars[v] ); - SCIPsortPtrReal((void**)andress, andcoefs, SCIPvarComp, nandress); + /* get linear solution */ + if( consanddata == NULL ) + solval = SCIPgetSolVal(scip, sol, vars[v]); + /* get term solution */ + else + { + SCIP_CONS* andcons = consanddata->origcons; + SCIP_VAR** andvars; + int nandvars; + int i; - SCIPdebugMsg(scip, "nlinvars = %d, nandress = %d\n", nlinvars, nandress); - SCIPdebugMsg(scip, "linear activity = %g\n", activity); + /* use transformed constraint if no original constraint exists */ + if( andcons == NULL ) + andcons = consanddata->cons; - /* compute and add solution values on terms */ - for( c = consdata->nconsanddatas - 1; c >= 0; --c ) - { - SCIP_VAR** andvars; - int nandvars; -#ifndef NDEBUG - SCIP_VAR* res; -#endif - andcons = consdata->consanddatas[c]->origcons; + assert(SCIPgetResultantAnd(scip, andcons) == var); - /* if after during or before presolving a solution will be transformed into original space and will be checked - * there, but origcons was already removed and only the pointer to the transformed and-constraint is existing - */ - if( andcons == NULL ) - { - andcons = consdata->consanddatas[c]->cons; - } - assert(andcons != NULL); + andvars = SCIPgetVarsAnd(scip, andcons); + nandvars = SCIPgetNVarsAnd(scip, andcons); + assert(nandvars == 0 || andvars != NULL); - andvars = SCIPgetVarsAnd(scip, andcons); - nandvars = SCIPgetNVarsAnd(scip, andcons); + solval = 1.0; -#ifndef NDEBUG - res = SCIPgetResultantAnd(scip, andcons); - assert(nandvars == 0 || (andvars != NULL && res != NULL)); - assert(res == andress[c]); -#endif + for( i = 0; i < nandvars; ++i ) + solval *= SCIPgetSolVal(scip, sol, andvars[i]); - andvalue = 1; - /* check if the and-constraint is violated */ - for( v = nandvars - 1; v >= 0; --v ) - { - andvalue *= SCIPgetSolVal(scip, sol, andvars[v]); - if( SCIPisFeasZero(scip, andvalue) ) - break; + if( var != vars[v] ) + solval = 1.0 - solval; } - activity += andvalue * andcoefs[c]; + + /* add activity contribution */ + activity += coefs[v] * solval; } - SCIPdebugMsg(scip, "lhs = %g, overall activity = %g, rhs = %g\n", lhs, activity, rhs); + + SCIPdebugMsg(scip, "lhs = %g, activity = %g, rhs = %g\n", lhs, activity, rhs); /* calculate absolute and relative violation */ lhsviol = lhs - activity; @@ -3645,7 +3557,7 @@ SCIP_RETCODE checkOrigPbCons( if( printreason ) { SCIP_CALL( SCIPprintCons(scip, cons, NULL ) ); - SCIPinfoMessage(scip, NULL, ";\n"); + SCIPinfoMessage(scip, NULL, ";\n"); SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", lhs - activity); /* print linear constraint in SCIP_DEBUG mode too */ @@ -3661,7 +3573,7 @@ SCIP_RETCODE checkOrigPbCons( if( printreason ) { SCIP_CALL( SCIPprintCons(scip, cons, NULL ) ); - SCIPinfoMessage(scip, NULL, ";\n"); + SCIPinfoMessage(scip, NULL, ";\n"); SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - rhs); } @@ -3669,10 +3581,6 @@ SCIP_RETCODE checkOrigPbCons( } /* free temporary memory */ - SCIPfreeBufferArray(scip, &andcoefs); - SCIPfreeBufferArray(scip, &andress); - SCIPfreeBufferArray(scip, &lincoefs); - SCIPfreeBufferArray(scip, &linvars); SCIPfreeBufferArray(scip, &coefs); SCIPfreeBufferArray(scip, &vars); @@ -3941,7 +3849,7 @@ SCIP_RETCODE copyConsPseudoboolean( consanddata = sourceconsdata->consanddatas[c]; assert(consanddata != NULL); - oldcons = consanddata->cons; + oldcons = consanddata->istransformed ? consanddata->cons : consanddata->origcons; assert(oldcons != NULL); targetandresultant = (SCIP_VAR*) SCIPhashmapGetImage(varmap, SCIPgetResultantAnd(sourcescip, oldcons)); @@ -4252,9 +4160,9 @@ SCIP_RETCODE correctLocksAndCaptures( SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */ SCIP_Real const newlhs, /**< new left hand side of pseudoboolean constraint */ SCIP_Real const newrhs, /**< new right hand side of pseudoboolean constraint */ - SCIP_VAR**const andress, /**< current and-resultants in pseudoboolean constraint */ - SCIP_Real*const andcoefs, /**< current and-resultants-coeffcients in pseudoboolean constraint */ - SCIP_Bool*const andnegs, /**< current negation status of and-resultants in pseudoboolean constraint */ + SCIP_VAR**const andress, /**< new and-resultants in pseudoboolean constraint */ + SCIP_Real*const andcoefs, /**< new and-resultants-coeffcients in pseudoboolean constraint */ + SCIP_Bool*const andnegs, /**< new negation status of and-resultants in pseudoboolean constraint */ int const nandress /**< number of current and-resultants in pseudoboolean constraint */ ) { @@ -4284,57 +4192,18 @@ SCIP_RETCODE correctLocksAndCaptures( consdata = SCIPconsGetData(cons); assert(consdata != NULL); - /* sort and-constraints after indices of corresponding and-resultants */ + /* sort and-constraints by the problem indices of corresponding and-resultants */ SCIPsortPtrRealBool((void**)(consdata->consanddatas), consdata->andcoefs, consdata->andnegs, resvarCompWithInactive, consdata->nconsanddatas); + /* sort and-resultants by their problem indices */ + SCIPsortPtrRealBool((void**)andress, andcoefs, andnegs, resvarComp, nandress); + consanddatas = consdata->consanddatas; oldandcoefs = consdata->andcoefs; oldandnegs = consdata->andnegs; nconsanddatas = consdata->nconsanddatas; assert(nconsanddatas == 0 || (consanddatas != NULL && oldandcoefs != NULL)); -#ifndef NDEBUG - /* check that and-resultants are sorted, and coefficents are not zero */ - for( c = nandress - 1; c > 0; --c ) - { - assert(!SCIPisZero(scip, andcoefs[c])); - assert(SCIPvarGetIndex(andress[c]) > SCIPvarGetIndex(andress[c - 1])); - } - /* check that consanddata objects are sorted due to the index of the corresponding resultants, and coefficents are - * not zero - */ - for( c = nconsanddatas - 1; c > 0; --c ) - { - SCIP_VAR* res1; - SCIP_VAR* res2; - - assert(consanddatas[c] != NULL); - - if( !consanddatas[c]->istransformed ) - continue; - - assert(!SCIPisZero(scip, oldandcoefs[c])); - assert(consanddatas[c - 1] != NULL); - - if( !consanddatas[c - 1]->istransformed ) - continue; - - assert(!SCIPisZero(scip, oldandcoefs[c - 1])); - - if( SCIPconsIsDeleted(consanddatas[c]->cons) || SCIPconsIsDeleted(consanddatas[c - 1]->cons) ) - continue; - - assert(consanddatas[c]->cons != NULL); - res1 = SCIPgetResultantAnd(scip, consanddatas[c]->cons); - assert(res1 != NULL); - assert(consanddatas[c - 1]->cons != NULL); - res2 = SCIPgetResultantAnd(scip, consanddatas[c - 1]->cons); - assert(res2 != NULL); - - assert(SCIPvarGetIndex(res1) >= SCIPvarGetIndex(res2)); - } -#endif - snewconsanddatas = nconsanddatas + nandress; /* allocate new block memory arrays */ @@ -4394,11 +4263,12 @@ SCIP_RETCODE correctLocksAndCaptures( assert(res2 != NULL); assert(SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res2) != NULL); - /* collect new consanddata objects in sorted order due to the variable index of corresponding and-resultants */ - if( SCIPvarGetIndex(res1) < SCIPvarGetIndex(res2) ) + /* collect new consanddata objects sorted with respect to the problem index of corresponding and-resultants */ + if( SCIPvarGetProbindex(res1) < SCIPvarGetProbindex(res2) ) { - assert(consanddatas[c]->nuses > 0); - --(consanddatas[c]->nuses); + assert(!SCIPisZero(scip, oldandcoefs[c])); + assert(consanddatas[c]->nuses > 0); + --(consanddatas[c]->nuses); /* remove old locks */ SCIP_CALL( removeOldLocks(scip, cons, consanddatas[c], oldandnegs[c] ? -oldandcoefs[c] : oldandcoefs[c], @@ -4406,16 +4276,17 @@ SCIP_RETCODE correctLocksAndCaptures( ++c; consdata->changed = TRUE; consdata->upgradetried = FALSE; - consdata->propagated = FALSE; - consdata->presolved = FALSE; + consdata->propagated = FALSE; + consdata->presolved = FALSE; } - else if( SCIPvarGetIndex(res1) > SCIPvarGetIndex(res2) ) + else if( SCIPvarGetProbindex(res1) > SCIPvarGetProbindex(res2) ) { + assert(!SCIPisZero(scip, andcoefs[c1])); assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)res2)); newconsanddatas[nnewconsanddatas] = (CONSANDDATA*) SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res2); newandcoefs[nnewconsanddatas] = andcoefs[c1]; newandnegs[nnewconsanddatas] = andnegs[c1]; - ++(newconsanddatas[nnewconsanddatas]->nuses); + ++(newconsanddatas[nnewconsanddatas]->nuses); /* add new locks */ SCIP_CALL( addNewLocks(scip, cons, newconsanddatas[nnewconsanddatas], newandnegs[nnewconsanddatas] ? @@ -4424,8 +4295,8 @@ SCIP_RETCODE correctLocksAndCaptures( consdata->changed = TRUE; consdata->upgradetried = FALSE; consdata->cliquesadded = FALSE; - consdata->propagated = FALSE; - consdata->presolved = FALSE; + consdata->propagated = FALSE; + consdata->presolved = FALSE; ++nnewconsanddatas; } @@ -4435,6 +4306,8 @@ SCIP_RETCODE correctLocksAndCaptures( SCIP_Bool lhschanged; SCIP_Bool rhschanged; + assert(!SCIPisZero(scip, oldandcoefs[c])); + assert(!SCIPisZero(scip, andcoefs[c1])); assert(SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res2) == consanddatas[c]); /* copy old consanddata object and new coefficent */ @@ -4507,16 +4380,16 @@ SCIP_RETCODE correctLocksAndCaptures( continue; } - assert(consanddatas[c]->nuses > 0); - --(consanddatas[c]->nuses); + assert(consanddatas[c]->nuses > 0); + --(consanddatas[c]->nuses); /* remove old locks */ SCIP_CALL( removeOldLocks(scip, cons, consanddatas[c], oldandnegs[c] ? -oldandcoefs[c] : oldandcoefs[c], consdata->lhs, consdata->rhs) ); consdata->changed = TRUE; consdata->upgradetried = FALSE; - consdata->propagated = FALSE; - consdata->presolved = FALSE; + consdata->propagated = FALSE; + consdata->presolved = FALSE; } } else if( c1 < nandress ) @@ -4531,7 +4404,7 @@ SCIP_RETCODE correctLocksAndCaptures( newconsanddatas[nnewconsanddatas] = (CONSANDDATA*) SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res2); newandcoefs[nnewconsanddatas] = andcoefs[c1]; newandnegs[nnewconsanddatas] = andnegs[c1]; - ++(newconsanddatas[nnewconsanddatas]->nuses); + ++(newconsanddatas[nnewconsanddatas]->nuses); /* add new locks */ SCIP_CALL( addNewLocks(scip, cons, newconsanddatas[nnewconsanddatas], newandnegs[nnewconsanddatas] ? @@ -4540,9 +4413,9 @@ SCIP_RETCODE correctLocksAndCaptures( ++nnewconsanddatas; consdata->changed = TRUE; consdata->upgradetried = FALSE; - consdata->cliquesadded = FALSE; - consdata->propagated = FALSE; - consdata->presolved = FALSE; + consdata->cliquesadded = FALSE; + consdata->propagated = FALSE; + consdata->presolved = FALSE; } } assert(c == nconsanddatas && c1 == nandress); @@ -4579,17 +4452,12 @@ SCIP_RETCODE correctLocksAndCaptures( consdata->presolved = FALSE; } - /* we need to re-sort and-constraints after indices of corresponding and-resultants, since we might have replaced - * negated variables - */ - SCIPsortPtrRealBool((void**)(consdata->consanddatas), consdata->andcoefs, consdata->andnegs, resvarCompWithInactive, consdata->nconsanddatas); - #ifndef NDEBUG consanddatas = consdata->consanddatas; nconsanddatas = consdata->nconsanddatas; assert(nconsanddatas == 0 || consanddatas != NULL); - /* check that consanddata objects are sorted with respect to the index of the corresponding resultants */ + /* check that consanddata objects are sorted with respect to the problem index of the corresponding resultants */ for( c = nconsanddatas - 1; c > 0; --c ) { SCIP_VAR* res1; @@ -4604,7 +4472,7 @@ SCIP_RETCODE correctLocksAndCaptures( res2 = SCIPgetResultantAnd(scip, consanddatas[c - 1]->cons); assert(res2 != NULL); - assert(SCIPvarGetIndex(res1) > SCIPvarGetIndex(res2)); + assert(SCIPvarGetProbindex(res1) > SCIPvarGetProbindex(res2)); } #endif @@ -4675,9 +4543,7 @@ SCIP_RETCODE addCliques( /* get variables and coefficients */ SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, NULL, &nvars) ); - /* calculate all not artificial linear variables and all artificial and-resultants which will be ordered like the - * 'consanddatas' such that the and-resultant of the and-constraint is the and-resultant in the 'andress' array - * afterwards + /* calculate all not artificial linear variables and all artificial and-resultants * @todo should we take into accout the negation status of the cliques? */ SCIP_CALL( getLinVarsAndAndRess(scip, cons, vars, NULL, nvars, linvars, NULL, &nlinvars, @@ -4775,7 +4641,7 @@ SCIP_RETCODE addCliques( if( *cutoff ) goto TERMINATE; - *nchgbds += nchgbdslocal; + *nchgbds += nchgbdslocal; (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_clq_%s_%s", SCIPconsGetName(cons), SCIPvarGetName(clqvars[0]), SCIPvarGetName(clqvars[1]) ); SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, consname, 2, clqvars, @@ -4818,7 +4684,7 @@ SCIP_RETCODE addCliques( if( *cutoff ) goto TERMINATE; - *nchgbds += nchgbdslocal; + *nchgbds += nchgbdslocal; (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_clq_%s_%s", SCIPconsGetName(cons), SCIPvarGetName(clqvars[0]), SCIPvarGetName(clqvars[1]) ); SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, consname, 2, clqvars, @@ -4944,7 +4810,7 @@ SCIP_RETCODE addCliques( if( *cutoff ) goto TERMINATE; - *nchgbds += nchgbdslocal; + *nchgbds += nchgbdslocal; (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_clq_%s_%s", SCIPconsGetName(cons), SCIPvarGetName(clqvars[0]), SCIPvarGetName(clqvars[1]) ); SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, consname, 2, clqvars, @@ -4988,7 +4854,7 @@ SCIP_RETCODE addCliques( if( *cutoff ) goto TERMINATE; - *nchgbds += nchgbdslocal; + *nchgbds += nchgbdslocal; (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_clq_%s_%s", SCIPconsGetName(cons), SCIPvarGetName(clqvars[0]), SCIPvarGetName(clqvars[1]) ); SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, consname, 2, clqvars, @@ -5108,6 +4974,12 @@ SCIP_RETCODE correctConshdlrdata( { CONSANDDATA** allconsanddatas; CONSANDDATA* consanddata; + SCIP_VAR** fixedvars = SCIPgetFixedVars(scip); + SCIP_VAR** activevars; + SCIP_Real* activescalars; + SCIP_Real activeconstant; + int nvars = SCIPgetNVars(scip); + int nfixedvars = SCIPgetNFixedVars(scip); int c; assert(scip != NULL); @@ -5116,9 +4988,20 @@ SCIP_RETCODE correctConshdlrdata( allconsanddatas = conshdlrdata->allconsanddatas; assert(allconsanddatas != NULL); - assert(conshdlrdata->nallconsanddatas > 0); + assert(conshdlrdata->nallconsanddatas >= 1); assert(conshdlrdata->nallconsanddatas <= conshdlrdata->sallconsanddatas); + if( nfixedvars >= 1 && nvars >= 1 ) + { + SCIP_CALL( SCIPallocBufferArray(scip, &activevars, nvars) ); + SCIP_CALL( SCIPallocBufferArray(scip, &activescalars, nvars) ); + } + else + { + activevars = NULL; + activescalars = NULL; + } + for( c = conshdlrdata->nallconsanddatas - 1; c >= 0; --c ) { SCIP_VAR** tmpvars; @@ -5178,8 +5061,8 @@ SCIP_RETCODE correctConshdlrdata( /* the consanddata object is not used anymore, so extract the and constraint and delete other data */ if( consanddata->nuses == 0 ) { - SCIP_Bool looseorcolumn; - SCIP_VARSTATUS varstatus; + SCIP_Bool looseorcolumn; + SCIP_VARSTATUS varstatus; if( consanddata->cons == NULL ) { @@ -5197,121 +5080,66 @@ SCIP_RETCODE correctConshdlrdata( SCIP_CALL( transformToOrig(scip, consanddata, conshdlrdata) ); - varstatus = SCIPvarGetStatus(SCIPgetResultantAnd(scip, consanddata->cons)); - looseorcolumn = (varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN); - -#if 1 - /* @note due to aggregations or fixings the resultant may need to be propagated later on, so we can only - * delete the and-constraint if the resultant is of column or loose status - * and is not an active variable of another (multi-)aggregated/negated variable - */ - if( looseorcolumn ) - { - SCIP_Bool del = TRUE; - int nfixedvars = SCIPgetNFixedVars(scip); - - if( nfixedvars > 0 ) - { - SCIP_VAR** fixedvars; - SCIP_VAR** scipfixedvars; - SCIP_VAR** activevars = NULL; - SCIP_Real* activescalars = NULL; - SCIP_Real activeconstant; - int nactivevars; - int requiredsize; - int pos; - int w; - - scipfixedvars = SCIPgetFixedVars(scip); - SCIP_CALL( SCIPduplicateBufferArray(scip, &fixedvars, scipfixedvars, nfixedvars) ); - - SCIPvarsGetProbvar(fixedvars, nfixedvars); - - /* all inactive variables have a loose, column, fixed or multi-aggregated variable as counterpart, - * for multi-aggregated variables, we need to check all active representatives - * @todo move this outside of the consanddata loop - */ - for( w = nfixedvars - 1; w >= 0; --w ) - { - if( SCIPvarGetStatus(fixedvars[w]) == SCIP_VARSTATUS_MULTAGGR ) - { - if( activevars == NULL ) - { - SCIP_CALL( SCIPallocBufferArray(scip, &activevars, SCIPgetNVars(scip)) ); - SCIP_CALL( SCIPallocBufferArray(scip, &activescalars, SCIPgetNVars(scip)) ); - } - assert(activevars != NULL); - assert(activescalars != NULL); - - activevars[0] = fixedvars[w]; - activescalars[0] = 1.0; - activeconstant = 0.0; - nactivevars = 1; - - SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activescalars, &nactivevars, SCIPgetNVars(scip), - &activeconstant, &requiredsize, TRUE) ); - assert(requiredsize <= SCIPgetNVars(scip)); - - if( nactivevars == 0 ) - { - --nfixedvars; - fixedvars[w] = fixedvars[nfixedvars]; - } - else - { - fixedvars[w] = activevars[0]; - - if( nactivevars > 1 ) - { - int i; - - SCIP_CALL( SCIPreallocBufferArray(scip, &fixedvars, nfixedvars + nactivevars - 1) ); - for( i = 1; i < nactivevars; ++i ) - { - assert(SCIPvarGetStatus(activevars[i]) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(activevars[i]) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(activevars[i]) == SCIP_VARSTATUS_FIXED); - fixedvars[nfixedvars] = activevars[i]; - ++nfixedvars; - } - } - } - } - - assert(SCIPvarGetStatus(fixedvars[w]) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(fixedvars[w]) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(fixedvars[w]) == SCIP_VARSTATUS_FIXED); - } + varstatus = SCIPvarGetStatus(SCIPgetResultantAnd(scip, consanddata->cons)); + looseorcolumn = (varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN); - if( activevars != NULL ) - { - SCIPfreeBufferArray(scip, &activevars); - SCIPfreeBufferArray(scip, &activescalars); - } + /* @note due to aggregations or fixings the resultant may need to be propagated later on, so we can only + * delete the and-constraint if the resultant is of column or loose status + * and is not an active variable of another (multi-)aggregated/negated variable + */ + if( looseorcolumn ) + { + SCIP_VAR* resvar = SCIPgetResultantAnd(scip, consanddata->cons); + SCIP_Bool del = TRUE; + int w; - SCIPsortPtr((void**)fixedvars, SCIPvarComp, nfixedvars); + assert(nvars >= 1); - if( SCIPsortedvecFindPtr((void**)fixedvars, SCIPvarComp, SCIPgetResultantAnd(scip, consanddata->cons), nfixedvars, &pos) ) - del = FALSE; + /* we need to check all active representatives */ + for( w = 0; w < nfixedvars && del; ++w ) + { + int nactivevars; + int requiredsize; + int i; + + assert(fixedvars != NULL); + assert(activevars != NULL); + assert(activescalars != NULL); + activevars[0] = fixedvars[w]; + activescalars[0] = 1.0; + activeconstant = 0.0; + nactivevars = 1; + SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activescalars, &nactivevars, nvars, + &activeconstant, &requiredsize, TRUE) ); + assert(requiredsize <= nvars); + + for( i = 0; i < nactivevars && del; ++i ) + { + assert(SCIPvarGetStatus(activevars[i]) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(activevars[i]) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(activevars[i]) == SCIP_VARSTATUS_FIXED); - SCIPfreeBufferArray(scip, &fixedvars); - } + if( activevars[i] == resvar ) + del = FALSE; + } + } - if( del ) - { - SCIP_CALL( SCIPdelCons(scip, consanddata->cons) ); - } - } -#endif + if( del ) + { + SCIP_CALL( SCIPdelCons(scip, consanddata->cons) ); + } + } - if( !SCIPconsIsDeleted(consanddata->cons) ) - { - /* change flags */ - if( !looseorcolumn ) - { - SCIP_CALL( SCIPsetConsInitial(scip, consanddata->cons, FALSE) ); + if( !SCIPconsIsDeleted(consanddata->cons) ) + { + /* change flags */ + if( !looseorcolumn ) + { + SCIP_CALL( SCIPsetConsInitial(scip, consanddata->cons, FALSE) ); #if 0 - SCIP_CALL( SCIPsetConsSeparated(scip, consanddata->cons, FALSE) ); + SCIP_CALL( SCIPsetConsSeparated(scip, consanddata->cons, FALSE) ); #endif - } - SCIP_CALL( SCIPsetConsChecked(scip, consanddata->cons, TRUE) ); - } + } + SCIP_CALL( SCIPsetConsChecked(scip, consanddata->cons, TRUE) ); + } /* remove consanddata from hashtable, if it existed only in transformed space */ if( consanddata->origcons == NULL ) @@ -5382,6 +5210,12 @@ SCIP_RETCODE correctConshdlrdata( consanddata->nnewvars = 0; } + if( activevars != NULL ) + { + SCIPfreeBufferArray(scip, &activescalars); + SCIPfreeBufferArray(scip, &activevars); + } + return SCIP_OKAY; } @@ -5449,63 +5283,23 @@ SCIP_RETCODE updateConsanddataUses( if( consanddata->nuses == 0 ) { SCIP_VAR* resvar; - SCIP_VARSTATUS varstatus; - SCIP_Bool looseorcolumn; + SCIP_VARSTATUS varstatus; + SCIP_Bool looseorcolumn; SCIP_CALL( transformToOrig(scip, consanddata, conshdlrdata) ); resvar = SCIPgetResultantAnd(scip, consanddata->cons); assert(resvar != NULL); - varstatus = SCIPvarGetStatus(resvar); - looseorcolumn = (varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN); + varstatus = SCIPvarGetStatus(resvar); + looseorcolumn = (varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN); -#if 1 - /* @note due to aggregations or fixings the resultant may need to be propagated later on, so we can only - * delete the and-constraint if the resultant is of column or loose status + /* @note due to aggregations or fixings the resultant may need to be propagated later on, so we can only + * delete the and-constraint if the resultant is of column or loose status * and is not an active variable of another (multi-)aggregated/negated variable - */ - if( looseorcolumn ) - { - SCIP_Bool delcons = TRUE; -#if 0 - const int nfixedvars = SCIPgetNFixedVars(scip); - - if( nfixedvars > 0 ) - { - SCIP_VAR** fixedvars; - SCIP_Bool foundmultiaggrvar = FALSE; /* workaround for multi-aggregated variables */ - int pos; - int w; - - SCIP_CALL( SCIPduplicateBufferArray(scip, &fixedvars, SCIPgetFixedVars(scip), nfixedvars) ); - - SCIPvarsGetProbvar(fixedvars, nfixedvars); - - /* all inactive variables have a loose, column, fixed or multi-aggregated variable as counterpart, but - * because we have only binary variables (in pseudobbolean contest) there should also be no - * multi-aggregated variable - * - * @todo for multi-aggregated variables check also all active representatives for this resultant - */ - for( w = nfixedvars - 1; w >= 0; --w ) - { - if( SCIPvarGetStatus(fixedvars[w]) == SCIP_VARSTATUS_MULTAGGR ) - foundmultiaggrvar = TRUE; - else - assert(SCIPvarGetStatus(fixedvars[w]) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(fixedvars[w]) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(fixedvars[w]) == SCIP_VARSTATUS_FIXED); - } - - SCIPsortPtr((void**)fixedvars, SCIPvarComp, nfixedvars); - - if( foundmultiaggrvar ) - delcons = FALSE; - else if( SCIPsortedvecFindPtr((void**)fixedvars, SCIPvarComp, resvar, nfixedvars, &pos) ) - delcons = FALSE; - - SCIPfreeBufferArray(scip, &fixedvars); - } -#endif + */ + if( looseorcolumn ) + { /* we can only delete and constraints if the resultant is an artificial variable and also active, because * then the assigned value is not of interest and the artificial and constraint does not need to be * fulfilled @@ -5513,42 +5307,23 @@ SCIP_RETCODE updateConsanddataUses( * if this variable is not such an artificial variable we need the IRRELEVANT vartype which should be the * correct way to fix this */ - if( delcons -#if 0 - && strlen(SCIPvarGetName(resvar)) > strlen(ARTIFICIALVARNAMEPREFIX) && - strncmp(SCIPvarGetName(resvar)+2, ARTIFICIALVARNAMEPREFIX, strlen(ARTIFICIALVARNAMEPREFIX)) == 0 -#endif - ) /*lint !e774*/ - { - assert(!SCIPconsIsChecked(consanddata->cons)); - SCIP_CALL( SCIPdelCons(scip, consanddata->cons) ); - } - } -#endif -#if 0 - /* @note due to aggregations or fixings the resultant may need to be propagated later on, so we can only - * delete the and-constraint if the resultant is of column or loose status - * and is not an active variable of another (multi-)aggregated/negated variable - */ - if( looseorcolumn ) - { - SCIP_CALL( SCIPdelCons(scip, consanddata->cons) ); - } -#endif + assert(!SCIPconsIsChecked(consanddata->cons)); + SCIP_CALL( SCIPdelCons(scip, consanddata->cons) ); + } - if( !SCIPconsIsDeleted(consanddata->cons) ) - { - /* change flags */ - if( !looseorcolumn ) - { - SCIP_CALL( SCIPsetConsInitial(scip, consanddata->cons, FALSE) ); + if( !SCIPconsIsDeleted(consanddata->cons) ) + { + /* change flags */ + if( !looseorcolumn ) + { + SCIP_CALL( SCIPsetConsInitial(scip, consanddata->cons, FALSE) ); #if 0 - SCIP_CALL( SCIPsetConsSeparated(scip, consanddata->cons, FALSE) ); + SCIP_CALL( SCIPsetConsSeparated(scip, consanddata->cons, FALSE) ); #endif - } - SCIP_CALL( SCIPsetConsChecked(scip, consanddata->cons, TRUE) ); - } + } + SCIP_CALL( SCIPsetConsChecked(scip, consanddata->cons, TRUE) ); + } /* remove consanddata from hashtable, if it existed only in transformed space */ if( consanddata->origcons == NULL ) @@ -5581,11 +5356,11 @@ SCIP_RETCODE checkSolution( SCIP*const scip, /**< SCIP data structure */ SCIP_VAR**const vars, /**< all variables which occur */ int const nvars, /**< number of all variables which appear in the pseudoboolean - * constraint - */ + * constraint + */ SCIP_Bool*const values, /**< values of all variables which appear in the pseudoboolean - * constraint - */ + * constraint + */ SCIP_VAR**const linvars, /**< linear variables */ SCIP_Real*const lincoefs, /**< linear coefficients */ int const nlinvars, /**< number of linear variables */ @@ -5597,8 +5372,8 @@ SCIP_RETCODE checkSolution( int const nconsanddatas, /**< number of all consanddata objects */ int const cnt, /**< number of variables set to 1 */ int*const xortype /**< pointer to save the possible xor type if a solution was valid and does - * not violate the old xortype - */ + * not violate the old xortype + */ ) { CONSANDDATA* consanddata; @@ -5633,16 +5408,16 @@ SCIP_RETCODE checkSolution( { if( SCIPsortedvecFindPtr((void**)vars, SCIPvarCompActiveAndNegated, linvars[v], nvars, &pos) ) /*lint !e613*/ { - if( values[pos] ) - value += lincoefs[v]; /*lint !e613*/ + if( values[pos] ) + value += lincoefs[v]; /*lint !e613*/ } else { - /* this cannot happen, all linear variables should be a part of 'vars' */ + /* this cannot happen, all linear variables should be a part of 'vars' */ SCIPABORT(); - *xortype = -1; /*lint !e527*/ - return SCIP_OKAY; + *xortype = -1; /*lint !e527*/ + return SCIP_OKAY; } } @@ -5660,13 +5435,13 @@ SCIP_RETCODE checkSolution( /* choose correct variable array to add locks for, we only add locks for now valid variables */ if( consanddata->nnewvars > 0 ) { - termvars = consanddata->newvars; - ntermvars = consanddata->nnewvars; + termvars = consanddata->newvars; + ntermvars = consanddata->nnewvars; } else { - termvars = consanddata->vars; - ntermvars = consanddata->nvars; + termvars = consanddata->vars; + ntermvars = consanddata->nvars; } assert(ntermvars > 0 && termvars != NULL); @@ -5678,31 +5453,31 @@ SCIP_RETCODE checkSolution( for( v = ntermvars - 1; v >= 0; --v ) { - SCIP_VAR* var; + SCIP_VAR* var; - assert(!negated[v] || (SCIPvarIsNegated(repvars[v]) && SCIPvarGetNegatedVar(repvars[v]) != NULL)); + assert(!negated[v] || (SCIPvarIsNegated(repvars[v]) && SCIPvarGetNegatedVar(repvars[v]) != NULL)); - var = ( negated[v] ? SCIPvarGetNegationVar(repvars[v]) : repvars[v]); - if( SCIPsortedvecFindPtr((void**)vars, SCIPvarCompActiveAndNegated, var, nvars, &pos) ) - { - if( (negated[v] && values[pos]) || (!negated[v] && !values[pos]) ) - { - val = FALSE; - break; - } - } - else - { - /* this cannot happen, all non-linear variables should be a part of 'vars' */ - SCIPABORT(); + var = ( negated[v] ? SCIPvarGetNegationVar(repvars[v]) : repvars[v]); + if( SCIPsortedvecFindPtr((void**)vars, SCIPvarCompActiveAndNegated, var, nvars, &pos) ) + { + if( (negated[v] && values[pos]) || (!negated[v] && !values[pos]) ) + { + val = FALSE; + break; + } + } + else + { + /* this cannot happen, all non-linear variables should be a part of 'vars' */ + SCIPABORT(); - *xortype = -1; /*lint !e527*/ - goto TERMINATE; - } + *xortype = -1; /*lint !e527*/ + goto TERMINATE; + } } if( val != consanddatanegs[c] ) - value += consanddatacoefs[c]; + value += consanddatacoefs[c]; } if( SCIPisEQ(scip, value, side) ) @@ -5710,32 +5485,32 @@ SCIP_RETCODE checkSolution( /* first solution is checked, so determine the possible xor upgrade */ if( *xortype == -1 ) { - if( cnt % 2 == 0 ) - *xortype = 0; - else - *xortype = 1; + if( cnt % 2 == 0 ) + *xortype = 0; + else + *xortype = 1; } /* check if this solution does not fit in all possible xor solutions */ else if( *xortype == 1 && cnt % 2 == 0 ) - *xortype = -1; + *xortype = -1; else if( *xortype == 0 && cnt % 2 == 1 ) - *xortype = -1; + *xortype = -1; } else { /* first not-solution is checked, so determine the possible xor upgrade */ if( *xortype == -1 ) { - if( cnt % 2 == 0 ) - *xortype = 1; - else - *xortype = 0; + if( cnt % 2 == 0 ) + *xortype = 1; + else + *xortype = 0; } /* check if this had to be a solution for an upgrade to an xor */ else if( *xortype == 1 && cnt % 2 == 1 ) - *xortype = -1; + *xortype = -1; else if( *xortype == 0 && cnt % 2 == 0 ) - *xortype = -1; + *xortype = -1; } TERMINATE: @@ -7100,7 +6875,7 @@ SCIP_RETCODE tryUpgrading( SCIP_CALL( tryUpgradingSetppc(scip, cons, conshdlrdata, ndelconss, naddconss, nfixedvars, nchgcoefs, nchgsides, cutoff) ); if( !SCIPconsIsDeleted(cons) ) { - SCIP_CALL( tryUpgradingXor(scip, cons, conshdlrdata, ndelconss, naddconss, nfixedvars, nchgcoefs, nchgsides, cutoff) ); + SCIP_CALL( tryUpgradingXor(scip, cons, conshdlrdata, ndelconss, naddconss, nfixedvars, nchgcoefs, nchgsides, cutoff) ); } break; #ifdef WITHEQKNAPSACK @@ -7201,7 +6976,7 @@ SCIP_RETCODE findAggregation( if( consanddatas[1]->nnewvars > 0 ) { if( nvars != consanddatas[1]->nnewvars ) - return SCIP_OKAY; + return SCIP_OKAY; } else if( nvars != consanddatas[1]->nvars ) return SCIP_OKAY; @@ -7236,11 +7011,11 @@ SCIP_RETCODE findAggregation( /* it appears that some fixed variables were not yet deleted */ if( SCIPvarGetLbGlobal(repvars[v-1]) > 0.5 || SCIPvarGetUbGlobal(repvars[v-1]) < 0.5 ) - goto TERMINATE; + goto TERMINATE; /* it appears that some fixed variables were not yet deleted */ if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 ) - goto TERMINATE; + goto TERMINATE; assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v])))); assert(SCIPvarIsActive(repvars[v-1]) || (SCIPvarIsNegated(repvars[v-1]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v-1])))); @@ -7258,7 +7033,7 @@ SCIP_RETCODE findAggregation( { /* it appears that some fixed variables were not yet deleted */ if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 ) - goto TERMINATE; + goto TERMINATE; assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v])))); assert(SCIPvarIsActive(repvars[v]) != negated[v]); @@ -7274,9 +7049,9 @@ SCIP_RETCODE findAggregation( /* get valid variables */ if( consanddatas[nconsanddatas - 1]->nnewvars > 0 ) - vars = consanddatas[c]->newvars; + vars = consanddatas[c]->newvars; else - vars = consanddatas[c]->vars; + vars = consanddatas[c]->vars; /* need to reset the negated flags */ BMSclearMemoryArray(negated, nvars); @@ -7289,47 +7064,47 @@ SCIP_RETCODE findAggregation( /* and-constraints have to be merged in order to check for aggregation */ for( v = 1; v < nvars; ++v ) { - SCIP_VAR* var1; - SCIP_VAR* var2; + SCIP_VAR* var1; + SCIP_VAR* var2; - /* it appears that some fixed variables were not yet deleted */ - if( SCIPvarGetLbGlobal(repvars[v-1]) > 0.5 || SCIPvarGetUbGlobal(repvars[v-1]) < 0.5 ) - goto TERMINATE; + /* it appears that some fixed variables were not yet deleted */ + if( SCIPvarGetLbGlobal(repvars[v-1]) > 0.5 || SCIPvarGetUbGlobal(repvars[v-1]) < 0.5 ) + goto TERMINATE; - /* it appears that some fixed variables were not yet deleted */ - if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 ) - goto TERMINATE; + /* it appears that some fixed variables were not yet deleted */ + if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 ) + goto TERMINATE; - assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v])))); - assert(SCIPvarIsActive(repvars[v-1]) || (SCIPvarIsNegated(repvars[v-1]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v-1])))); - assert(SCIPvarIsActive(repvars[v]) != negated[v]); - assert(SCIPvarIsActive(repvars[v-1]) != negated[v-1]); + assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v])))); + assert(SCIPvarIsActive(repvars[v-1]) || (SCIPvarIsNegated(repvars[v-1]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v-1])))); + assert(SCIPvarIsActive(repvars[v]) != negated[v]); + assert(SCIPvarIsActive(repvars[v-1]) != negated[v-1]); - var1 = (negated[v-1] ? SCIPvarGetNegationVar(repvars[v-1]) : repvars[v-1]); - var2 = (negated[v] ? SCIPvarGetNegationVar(repvars[v]) : repvars[v]); - assert(var1 != var2); + var1 = (negated[v-1] ? SCIPvarGetNegationVar(repvars[v-1]) : repvars[v-1]); + var2 = (negated[v] ? SCIPvarGetNegationVar(repvars[v]) : repvars[v]); + assert(var1 != var2); } #endif /* update the statuses of all appearing variables */ for( v = nvars - 1; v >= 0; --v ) { - /* it appears that some fixed variables were not yet deleted */ - if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 ) - goto TERMINATE; + /* it appears that some fixed variables were not yet deleted */ + if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 ) + goto TERMINATE; - assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v])))); - assert(SCIPvarIsActive(repvars[v]) != negated[v]); + assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v])))); + assert(SCIPvarIsActive(repvars[v]) != negated[v]); - /* we can only find an aggregation if all and constraints have the same variables */ - if( SCIPsortedvecFindPtr((void**)allvars, SCIPvarCompActiveAndNegated, repvars[v], nvars, &pos) ) - { - assert(pos >= 0 && pos < nvars); + /* we can only find an aggregation if all and constraints have the same variables */ + if( SCIPsortedvecFindPtr((void**)allvars, SCIPvarCompActiveAndNegated, repvars[v], nvars, &pos) ) + { + assert(pos >= 0 && pos < nvars); - ++(varcount[negated[v]][pos]); - } - else - goto TERMINATE; + ++(varcount[negated[v]][pos]); + } + else + goto TERMINATE; } } @@ -7343,16 +7118,16 @@ SCIP_RETCODE findAggregation( { for( v = nvars - 1; v >= 0; --v ) { - assert(SCIPvarIsActive(allvars[v])); + assert(SCIPvarIsActive(allvars[v])); - if( varcount[i][v] == 0 ) - ++zerocount; - else if( varcount[i][v] == 1 ) - ++onecount; - else if( varcount[i][v] == 2 ) - ++twocount; - else - ++othercount; + if( varcount[i][v] == 0 ) + ++zerocount; + else if( varcount[i][v] == 1 ) + ++onecount; + else if( varcount[i][v] == 2 ) + ++twocount; + else + ++othercount; } } @@ -7364,103 +7139,103 @@ SCIP_RETCODE findAggregation( */ if( nconsanddatas == 2 && twocount == nvars - 1 && onecount == 2 && zerocount == 1 ) { - SCIP_VAR** consvars; - SCIP_Real* conscoefs; - int nconsvars; - SCIP_VAR* linvar; - SCIP_Real lincoef; - int nlinvars; + SCIP_VAR** consvars; + SCIP_Real* conscoefs; + int nconsvars; + SCIP_VAR* linvar; + SCIP_Real lincoef; + int nlinvars; - /* allocate temporary memory */ - SCIP_CALL( SCIPallocBufferArray(scip, &consvars, consdata->nlinvars + nconsanddatas) ); - SCIP_CALL( SCIPallocBufferArray(scip, &conscoefs, consdata->nlinvars + nconsanddatas) ); + /* allocate temporary memory */ + SCIP_CALL( SCIPallocBufferArray(scip, &consvars, consdata->nlinvars + nconsanddatas) ); + SCIP_CALL( SCIPallocBufferArray(scip, &conscoefs, consdata->nlinvars + nconsanddatas) ); - /* get variables and coefficients */ - SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, consvars, conscoefs, &nconsvars) ); - assert(nconsvars == consdata->nlinvars + nconsanddatas); - assert(conscoefs != NULL); + /* get variables and coefficients */ + SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, consvars, conscoefs, &nconsvars) ); + assert(nconsvars == consdata->nlinvars + nconsanddatas); + assert(conscoefs != NULL); #ifndef NDEBUG - /* all coefficients have to be 1 */ - for( v = 0; v < nconsvars; ++v ) - assert(SCIPisEQ(scip, conscoefs[v], 1.0)); + /* all coefficients have to be 1 */ + for( v = 0; v < nconsvars; ++v ) + assert(SCIPisEQ(scip, conscoefs[v], 1.0)); #endif - linvar = NULL; + linvar = NULL; - /* calculate all not artificial linear variables */ - SCIP_CALL( getLinVarsAndAndRess(scip, cons, consvars, conscoefs, nconsvars, &linvar, &lincoef, &nlinvars, + /* calculate all not artificial linear variables */ + SCIP_CALL( getLinVarsAndAndRess(scip, cons, consvars, conscoefs, nconsvars, &linvar, &lincoef, &nlinvars, NULL, NULL, NULL, NULL) ); - assert(nlinvars == 1); - assert(linvar != NULL); - - SCIPfreeBufferArray(scip, &conscoefs); - SCIPfreeBufferArray(scip, &consvars); - - /* if all and-constraints have exactly two variables */ - if( nvars == 2 ) - { - SCIP_VAR* var; - SCIP_Bool breaked; - SCIP_Bool redundant; - SCIP_Bool infeasible; - SCIP_Bool aggregated; - - var = NULL; - breaked = FALSE; - - /* find necessary variables, which only occur once */ - for( i = 1; i >= 0; --i ) - { - for( v = nvars - 1; v >= 0; --v ) - { - assert(i == 1 || SCIPvarGetNegatedVar(allvars[v]) != NULL); - if( varcount[i][v] == 2 ) - { - var = i ? SCIPvarGetNegatedVar(allvars[v]) : allvars[v]; - - breaked = TRUE; - break; - } - } - - if( breaked ) - break; - } - assert(var != NULL); - - SCIPdebugMsg(scip, "aggregating variables <%s> == 1 - <%s> in pseudoboolean <%s>\n", SCIPvarGetName(linvar), SCIPvarGetName(var), SCIPconsGetName(cons)); - - SCIP_CALL( SCIPaggregateVars(scip, linvar, var, 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) ); - - SCIPdebugPrintCons(scip, cons, NULL); - SCIPdebugMsg(scip, "aggregation of variables: <%s> == 1 - <%s>, infeasible = %u, aggregated = %u\n", SCIPvarGetName(linvar), SCIPvarGetName(var), infeasible, aggregated); - - if( infeasible ) - *cutoff = TRUE; - else - { - if( aggregated ) - ++(*naggrvars); - - /* delete old constraints */ - SCIP_CALL( SCIPdelCons(scip, consdata->lincons) ); - SCIP_CALL( SCIPdelCons(scip, cons) ); - (*ndelconss) += 2; - } - } + assert(nlinvars == 1); + assert(linvar != NULL); + + SCIPfreeBufferArray(scip, &conscoefs); + SCIPfreeBufferArray(scip, &consvars); + + /* if all and-constraints have exactly two variables */ + if( nvars == 2 ) + { + SCIP_VAR* var; + SCIP_Bool breaked; + SCIP_Bool redundant; + SCIP_Bool infeasible; + SCIP_Bool aggregated; + + var = NULL; + breaked = FALSE; + + /* find necessary variables, which only occur once */ + for( i = 1; i >= 0; --i ) + { + for( v = nvars - 1; v >= 0; --v ) + { + assert(i == 1 || SCIPvarGetNegatedVar(allvars[v]) != NULL); + if( varcount[i][v] == 2 ) + { + var = i ? SCIPvarGetNegatedVar(allvars[v]) : allvars[v]; + + breaked = TRUE; + break; + } + } + + if( breaked ) + break; + } + assert(var != NULL); + + SCIPdebugMsg(scip, "aggregating variables <%s> == 1 - <%s> in pseudoboolean <%s>\n", SCIPvarGetName(linvar), SCIPvarGetName(var), SCIPconsGetName(cons)); + + SCIP_CALL( SCIPaggregateVars(scip, linvar, var, 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) ); + + SCIPdebugPrintCons(scip, cons, NULL); + SCIPdebugMsg(scip, "aggregation of variables: <%s> == 1 - <%s>, infeasible = %u, aggregated = %u\n", SCIPvarGetName(linvar), SCIPvarGetName(var), infeasible, aggregated); + + if( infeasible ) + *cutoff = TRUE; + else + { + if( aggregated ) + ++(*naggrvars); + + /* delete old constraints */ + SCIP_CALL( SCIPdelCons(scip, consdata->lincons) ); + SCIP_CALL( SCIPdelCons(scip, cons) ); + (*ndelconss) += 2; + } + } #if 0 - else - { - /* @todo */ - /* delete allvars[samepos] from all and-constraints which appear in this pseudoboolean constraint, and delete - * all but one of the remaining and-constraint - * - * it is the same like aggregating linvar with the resultant of the product, which is the same in all and- - * constraints without allvars[samepos] - * - * e.g. x1 + x2*x_3*...x_n + ~x2*x_3*...x_n = 1 => x1 = 1 - x_3*...x_n - */ - } + else + { + /* @todo */ + /* delete allvars[samepos] from all and-constraints which appear in this pseudoboolean constraint, and delete + * all but one of the remaining and-constraint + * + * it is the same like aggregating linvar with the resultant of the product, which is the same in all and- + * constraints without allvars[samepos] + * + * e.g. x1 + x2*x_3*...x_n + ~x2*x_3*...x_n = 1 => x1 = 1 - x_3*...x_n + */ + } #endif } /*lint !e438*/ /* we have a constraint in the form of: x1 + x2 * x3 + ~x2 * x3 + ~x2 * ~x3 == 1 @@ -7472,83 +7247,83 @@ SCIP_RETCODE findAggregation( */ else if( nvars == 2 && nconsanddatas == 3 && twocount == 2 && onecount == 2 && zerocount == 0) { - SCIP_VAR** consvars; - SCIP_Real* conscoefs; - int nconsvars; - SCIP_VAR* linvar; - SCIP_Real lincoef; - int nlinvars; - SCIP_VAR* newandvars[2]; - SCIP_Bool breaked; - SCIP_CONS* newcons; - char name[SCIP_MAXSTRLEN]; - - /* allocate temporary memory */ - SCIP_CALL( SCIPallocBufferArray(scip, &consvars, consdata->nlinvars + nconsanddatas) ); - SCIP_CALL( SCIPallocBufferArray(scip, &conscoefs, consdata->nlinvars + nconsanddatas) ); - - /* get variables and coefficients */ - SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, consvars, conscoefs, &nconsvars) ); - assert(nconsvars == consdata->nlinvars + nconsanddatas); - assert(conscoefs != NULL); + SCIP_VAR** consvars; + SCIP_Real* conscoefs; + int nconsvars; + SCIP_VAR* linvar; + SCIP_Real lincoef; + int nlinvars; + SCIP_VAR* newandvars[2]; + SCIP_Bool breaked; + SCIP_CONS* newcons; + char name[SCIP_MAXSTRLEN]; + + /* allocate temporary memory */ + SCIP_CALL( SCIPallocBufferArray(scip, &consvars, consdata->nlinvars + nconsanddatas) ); + SCIP_CALL( SCIPallocBufferArray(scip, &conscoefs, consdata->nlinvars + nconsanddatas) ); + + /* get variables and coefficients */ + SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, consvars, conscoefs, &nconsvars) ); + assert(nconsvars == consdata->nlinvars + nconsanddatas); + assert(conscoefs != NULL); #ifndef NDEBUG - /* all coefficients have to be 1 */ - for( v = 0; v < nconsvars; ++v ) - assert(SCIPisEQ(scip, conscoefs[v], 1.0)); + /* all coefficients have to be 1 */ + for( v = 0; v < nconsvars; ++v ) + assert(SCIPisEQ(scip, conscoefs[v], 1.0)); #endif - linvar = NULL; + linvar = NULL; - /* calculate all not artificial linear variables */ - SCIP_CALL( getLinVarsAndAndRess(scip, cons, consvars, conscoefs, nconsvars, &linvar, &lincoef, &nlinvars, + /* calculate all not artificial linear variables */ + SCIP_CALL( getLinVarsAndAndRess(scip, cons, consvars, conscoefs, nconsvars, &linvar, &lincoef, &nlinvars, NULL, NULL, NULL, NULL) ); - assert(nlinvars == 1); - assert(linvar != NULL); - - SCIPfreeBufferArray(scip, &conscoefs); - SCIPfreeBufferArray(scip, &consvars); - - newandvars[0] = NULL; - newandvars[1] = NULL; - breaked = FALSE; - - /* find necessary variables, which only occur once */ - for( i = 1; i >= 0; --i ) - { - for( v = nvars - 1; v >= 0; --v ) - { - assert(i == 1 || SCIPvarGetNegatedVar(allvars[v]) != NULL); - if( varcount[i][v] == 1 ) - { - if( newandvars[0] == NULL ) - newandvars[0] = i ? SCIPvarGetNegatedVar(allvars[v]) : allvars[v]; - else - { - assert(newandvars[1] == NULL); - newandvars[1] = i ? SCIPvarGetNegatedVar(allvars[v]) : allvars[v]; - - breaked = TRUE; - break; - } - } - } - - if( breaked ) - break; - } - assert(newandvars[0] != NULL && newandvars[1] != NULL); - - (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "andcons_%s_%s", SCIPconsGetName(cons), SCIPvarGetName(linvar)); - SCIP_CALL( SCIPcreateConsAnd(scip, &newcons, name, linvar, nvars, newandvars, - TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) ); - SCIP_CALL( SCIPaddCons(scip, newcons) ); - SCIPdebugPrintCons(scip, newcons, NULL); - SCIP_CALL( SCIPreleaseCons(scip, &newcons) ); - - /* delete old constraints */ - SCIP_CALL( SCIPdelCons(scip, consdata->lincons) ); - SCIP_CALL( SCIPdelCons(scip, cons) ); - (*ndelconss) += 2; + assert(nlinvars == 1); + assert(linvar != NULL); + + SCIPfreeBufferArray(scip, &conscoefs); + SCIPfreeBufferArray(scip, &consvars); + + newandvars[0] = NULL; + newandvars[1] = NULL; + breaked = FALSE; + + /* find necessary variables, which only occur once */ + for( i = 1; i >= 0; --i ) + { + for( v = nvars - 1; v >= 0; --v ) + { + assert(i == 1 || SCIPvarGetNegatedVar(allvars[v]) != NULL); + if( varcount[i][v] == 1 ) + { + if( newandvars[0] == NULL ) + newandvars[0] = i ? SCIPvarGetNegatedVar(allvars[v]) : allvars[v]; + else + { + assert(newandvars[1] == NULL); + newandvars[1] = i ? SCIPvarGetNegatedVar(allvars[v]) : allvars[v]; + + breaked = TRUE; + break; + } + } + } + + if( breaked ) + break; + } + assert(newandvars[0] != NULL && newandvars[1] != NULL); + + (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "andcons_%s_%s", SCIPconsGetName(cons), SCIPvarGetName(linvar)); + SCIP_CALL( SCIPcreateConsAnd(scip, &newcons, name, linvar, nvars, newandvars, + TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) ); + SCIP_CALL( SCIPaddCons(scip, newcons) ); + SCIPdebugPrintCons(scip, newcons, NULL); + SCIP_CALL( SCIPreleaseCons(scip, &newcons) ); + + /* delete old constraints */ + SCIP_CALL( SCIPdelCons(scip, consdata->lincons) ); + SCIP_CALL( SCIPdelCons(scip, cons) ); + (*ndelconss) += 2; } /*lint !e438*/ } @@ -8064,9 +7839,9 @@ SCIP_DECL_CONSINITPRE(consInitprePseudoboolean) cons = conss[c]; assert(cons != NULL); - /* only added constraints can be upgraded */ - if( !SCIPconsIsAdded(cons) ) - continue; + /* only added constraints can be upgraded */ + if( !SCIPconsIsAdded(cons) ) + continue; consdata = SCIPconsGetData(cons); assert(consdata != NULL); @@ -8644,10 +8419,7 @@ SCIP_DECL_CONSPRESOL(consPresolPseudoboolean) SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) ); assert(nvars == 0 || (coefs != NULL)); - /* calculate all not artificial linear variables and all artificial and-resultants which will be ordered like the - * 'consanddatas' such that the and-resultant of the and-constraint is the and-resultant in the 'andress' array - * afterwards - */ + /* calculate all not artificial linear variables and all artificial and-resultants */ SCIP_CALL( getLinVarsAndAndRess(scip, cons, vars, coefs, nvars, linvars, lincoefs, &nlinvars, andress, andcoefs, andnegs, &nandress) ); @@ -8667,8 +8439,8 @@ SCIP_DECL_CONSPRESOL(consPresolPseudoboolean) if( consdata->changed && !SCIPisStopped(scip) ) { - /* check if we can aggregated some variables */ - SCIP_CALL( findAggregation(scip, cons, conshdlrdata, ndelconss, naggrvars, &cutoff) ); + /* check if we can aggregated some variables */ + SCIP_CALL( findAggregation(scip, cons, conshdlrdata, ndelconss, naggrvars, &cutoff) ); } /* if aggregation also deleted the constraint we can go to the next */ @@ -8712,7 +8484,7 @@ SCIP_DECL_CONSPRESOL(consPresolPseudoboolean) /* reset changed flag */ if( SCIPconsIsActive(cons) ) { - consdata->changed = FALSE; + consdata->changed = FALSE; } /* free temporary memory */ @@ -8998,10 +8770,7 @@ SCIP_DECL_CONSGETVARS(consGetVarsPseudoboolean) /* get variables and coefficient of linear constraint */ SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, linconsvars, NULL, &nlinconsvars) ); - /* calculate all non-artificial linear variables and all artificial and-resultants which will be ordered like the - * 'consanddatas' such that the and-resultant of the and-constraint is the and-resultant in the 'andress' array - * afterwards - */ + /* calculate all non-artificial linear variables and all artificial and-resultants */ SCIP_CALL( getLinVarsAndAndRess(scip, cons, linconsvars, NULL, nlinconsvars, linvars, NULL, &nlinvars, andress, NULL, NULL, &nandress) ); assert(nlinconsvars == nlinvars + nandress); @@ -9047,9 +8816,9 @@ SCIP_DECL_CONSGETVARS(consGetVarsPseudoboolean) /* not enough space for all variables */ if( varssize <= nvars ) { - (*success) = FALSE; + (*success) = FALSE; - goto TERMINATE; + goto TERMINATE; } /* add the resultant */ @@ -9059,25 +8828,25 @@ SCIP_DECL_CONSGETVARS(consGetVarsPseudoboolean) /* add all and-operands and the resultant */ if( !SCIPconsIsDeleted(andcons) ) { - int noperands = SCIPgetNVarsAnd(scip, andcons); + int noperands = SCIPgetNVarsAnd(scip, andcons); - assert(noperands >= 0); + assert(noperands >= 0); - /* not enough space for all variables */ - if( varssize < nvars + noperands ) - { - (*success) = FALSE; + /* not enough space for all variables */ + if( varssize < nvars + noperands ) + { + (*success) = FALSE; - goto TERMINATE; - } + goto TERMINATE; + } - /* copy operands */ - if( noperands > 0 ) - { - assert(SCIPgetVarsAnd(scip, andcons) != NULL); - BMScopyMemoryArray(&(vars[nvars]), SCIPgetVarsAnd(scip, andcons), noperands); /*lint !e866*/ - nvars += noperands; - } + /* copy operands */ + if( noperands > 0 ) + { + assert(SCIPgetVarsAnd(scip, andcons) != NULL); + BMScopyMemoryArray(&(vars[nvars]), SCIPgetVarsAnd(scip, andcons), noperands); /*lint !e866*/ + nvars += noperands; + } } } @@ -9155,10 +8924,7 @@ SCIP_DECL_CONSGETNVARS(consGetNVarsPseudoboolean) /* get variables and coefficient of linear constraint */ SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, linconsvars, NULL, &nlinconsvars) ); - /* calculate all non-artificial linear variables and all artificial and-resultants which will be ordered like the - * 'consanddatas' such that the and-resultant of the and-constraint is the and-resultant in the 'andress' array - * afterwards - */ + /* calculate all non-artificial linear variables and all artificial and-resultants */ SCIP_CALL( getLinVarsAndAndRess(scip, cons, linconsvars, NULL, nlinconsvars, linvars, NULL, &nlinvars, andress, NULL, NULL, &nandress) ); assert(nlinconsvars == nlinvars + nandress); @@ -9197,13 +8963,13 @@ SCIP_DECL_CONSGETNVARS(consGetNVarsPseudoboolean) if( SCIPconsIsDeleted(andcons) ) { - /* only add one for the resultant */ - ++(*nvars); + /* only add one for the resultant */ + ++(*nvars); } else { - /* add all and-operands and one for the resultant */ - *nvars += SCIPgetNVarsAnd(scip, andcons) + 1; + /* add all and-operands and one for the resultant */ + *nvars += SCIPgetNVarsAnd(scip, andcons) + 1; } } diff --git a/src/scip/reader_opb.c b/src/scip/reader_opb.c index 2f1de12307..170383db4f 100644 --- a/src/scip/reader_opb.c +++ b/src/scip/reader_opb.c @@ -27,6 +27,7 @@ * @brief pseudo-Boolean file reader (opb format) * @author Stefan Heinz * @author Michael Winkler + * @author Dominik Kamp * * This file reader parses the @a opb format and is also used by the @a wbo reader for the @a wbo format. For a * detailed description of this format see @@ -843,7 +844,7 @@ SCIP_RETCODE readCoefficients( if( strcmp(opbinput->token, ":") == 0 ) { /* the second token was a colon ':' the first token is a constraint name */ - (void)SCIPmemccpy(name, opbinput->tokenbuf, '\0', SCIP_MAXSTRLEN); + (void)SCIPmemccpy(name, opbinput->tokenbuf, '\0', SCIP_MAXSTRLEN); name[SCIP_MAXSTRLEN-1] = '\0'; SCIPdebugMsg(scip, "(line %d) read constraint name: '%s'\n", opbinput->linenumber, name); @@ -1326,16 +1327,16 @@ SCIP_RETCODE setObjective( assert(coefs != NULL); if( SCIPvarIsNegated(linvars[v]) ) - { - SCIP_VAR* negvar = SCIPvarGetNegationVar(linvars[v]); - - SCIP_CALL( SCIPaddOrigObjoffset(scip, coefs[v]) ); - SCIP_CALL( SCIPaddVarObj(scip, negvar, -scale * coefs[v]) ); - } - else - { - SCIP_CALL( SCIPaddVarObj(scip, linvars[v], scale * coefs[v]) ); - } + { + SCIP_VAR* negvar = SCIPvarGetNegationVar(linvars[v]); + + SCIP_CALL( SCIPaddOrigObjoffset(scip, coefs[v]) ); + SCIP_CALL( SCIPaddVarObj(scip, negvar, -scale * coefs[v]) ); + } + else + { + SCIP_CALL( SCIPaddVarObj(scip, linvars[v], scale * coefs[v]) ); + } } } @@ -1640,7 +1641,7 @@ SCIP_RETCODE getMaxAndConsDim( nproducts = strstr(opbinput->linebuf, "#product= "); if( nproducts != NULL ) { - const char delimchars[] = " \t"; + const char delimchars[] = " \t"; char* pos; nproducts += strlen("#product= "); @@ -2091,8 +2092,8 @@ SCIP_RETCODE computeAndConstraintInfos( /* check same position with new variable, so we do not increase v */ } - else - ++v; + else + ++v; } } SCIPfreeBufferArray(scip, &shouldnotbeinand); @@ -2485,7 +2486,7 @@ SCIP_RETCODE writeOpbObjective( } #endif - for( v = nvars - 1; v >= 0; --v ) + for( v = 0; v < nvars; ++v ) { SCIP_Bool negated; var = vars[v]; /*lint !e613 */ @@ -2629,25 +2630,25 @@ SCIP_RETCODE printNLRow( /* replace and-resultant with corresponding variables */ if( SCIPsortedvecFindPtr((void**)resvars, SCIPvarComp, var, nresvars, &pos) ) { - int a; + int a; assert(andvars != NULL); assert(nandvars != NULL); assert(pos >= 0 && nandvars[pos] > 0 && andvars[pos] != NULL); assert(andvars[pos][nandvars[pos] - 1] != NULL); - negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]); + negated = SCIPvarIsNegated(andvars[pos][nandvars[pos] - 1]); if( vals[v] * (*mult) > (SCIP_Real)SCIP_LONGINT_MAX ) { SCIPerrorMessage("Integral coefficient to big (mult = %" SCIP_LONGINT_FORMAT ", value = %g, mult*value = %g, printingvalue = %" SCIP_LONGINT_FORMAT ")for printing in opb format.\n", *mult, vals[v], vals[v] * (*mult), (SCIP_Longint) SCIPround(scip, vals[v] * (*mult))); } - /* print and-vars */ - (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s", - (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "", - strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x") ); - appendBuffer(scip, file, linebuffer, &linecnt, buffer); + /* print and-vars */ + (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s", + (SCIP_Longint) SCIPround(scip, vals[v] * (*mult)), multisymbol, negated ? "~" : "", + strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(andvars[pos][nandvars[pos] - 1]) : andvars[pos][nandvars[pos] - 1]), "x") ); + appendBuffer(scip, file, linebuffer, &linecnt, buffer); for(a = nandvars[pos] - 2; a >= 0; --a ) { @@ -2972,303 +2973,14 @@ SCIP_RETCODE printLinearCons( return retcode; } -/* print row in OPB format to file stream */ -static -SCIP_RETCODE printPBRow( - SCIP*const scip, /**< SCIP data structure */ - FILE*const file, /**< output file (or NULL for standard output) */ - const char* type, /**< row type ("=" or ">=") */ - SCIP_VAR**const linvars, /**< array of variables */ - SCIP_Real*const linvals, /**< array of values */ - int const nlinvars, /**< number of variables */ - SCIP_VAR***const termvars, /**< term array with array of variables to print */ - int*const ntermvars, /**< array with number of variables in each term */ - SCIP_Real*const termvals, /**< array of coefficient values for non-linear variables */ - int const ntermvals, /**< number non-linear variables in the problem */ - SCIP_Bool**const negatedarrays, /**< array of arrays to know which variable in a non-linear part is negated */ - SCIP_VAR*const indvar, /**< indicator variable, or NULL */ - SCIP_Real lhs, /**< left hand side */ - SCIP_Longint* mult, /**< multiplier for the coefficients */ - const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */ - ) -{ - SCIP_VAR* var; - char buffer[OPB_MAX_LINELEN]; - char linebuffer[OPB_MAX_LINELEN + 1]; - int v; - int t; - int linecnt; - - assert(scip != NULL); - assert(strcmp(type, "=") == 0 || strcmp(type, ">=") == 0); - assert(linvars != NULL || nlinvars == 0); - assert(linvals != NULL || nlinvars == 0); - assert(termvars != NULL || ntermvals == 0); - assert(ntermvars != NULL || ntermvals == 0); - assert(termvals != NULL || ntermvals == 0); - assert(negatedarrays != NULL || ntermvals == 0); - assert(mult != NULL); - - clearBuffer(linebuffer, &linecnt); - - /* if we found the topcost linear inequality which gives us the maximal cost which could be violated by our solution, - * we can stop printing because it is an artificial constraint - */ - if( ntermvals == 0 && nlinvars > 0 && strstr(SCIPvarGetName(linvars[0]), INDICATORVARNAME) != NULL ) /*lint !e613 */ - return SCIP_OKAY; - - /* check if all linear coefficients are internal; if not commentstart multiplier */ - for( v = 0; v < nlinvars; ++v ) - { - while( !SCIPisIntegral(scip, linvals[v] * (*mult)) ) /*lint !e613 */ - { - if( ABS(*mult) > ABS(*mult * 10) ) - return SCIP_INVALIDDATA; - (*mult) *= 10; - } - } - - /* check if all non-linear coefficients are internal; if not commentstart multiplier */ - for( v = 0; v < ntermvals; ++v ) - { - while( !SCIPisIntegral(scip, termvals[v] * (*mult)) ) /*lint !e613 */ - { - if( ABS(*mult) > ABS(*mult * 10) ) - return SCIP_INVALIDDATA; - (*mult) *= 10; - } - } - - while( !SCIPisIntegral(scip, lhs * (*mult)) ) - { - if( ABS(*mult) > ABS(*mult * 10) ) - return SCIP_INVALIDDATA; - (*mult) *= 10; - } - - /* print comment line if we have to multiply the coefficients to get integrals */ - if( ABS(*mult) != 1 ) - SCIPinfoMessage(scip, file, "* the following constraint is multiplied by %" SCIP_LONGINT_FORMAT " to get integral coefficients\n", ABS(*mult) ); - - /* if indicator variable exist we have a soft constraint */ - if( indvar != NULL ) - { - SCIP_Real weight; - - weight = SCIPvarGetObj(indvar); - (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "[%+g] ", weight); - appendBuffer(scip, file, linebuffer, &linecnt, buffer); - } - - /* print linear part */ - for( v = 0; v < nlinvars; ++v ) - { - SCIP_Bool negated; - - var = linvars[v]; /*lint !e613 */ - assert(var != NULL); - - negated = SCIPvarIsNegated(var); - - (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT "%s%s%s ", - (SCIP_Longint) SCIPround(scip, linvals[v] * (*mult)), multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x")); /*lint !e613 */ - appendBuffer(scip, file, linebuffer, &linecnt, buffer); - } - - /* print non-linear part */ - for( t = 0; t < ntermvals; ++t ) - { - (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%+" SCIP_LONGINT_FORMAT, (SCIP_Longint) SCIPround(scip, termvals[t] * (*mult))); /*lint !e613 */ - appendBuffer(scip, file, linebuffer, &linecnt, buffer); - - for( v = 0; v < ntermvars[t]; ++v ) /*lint !e613 */ - { - SCIP_Bool negated; - - var = termvars[t][v]; /*lint !e613 */ - assert(var != NULL); - - negated = negatedarrays[t][v]; /*lint !e613 */ - - (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s%s%s", multisymbol, negated ? "~" : "", strstr(SCIPvarGetName(negated ? SCIPvarGetNegationVar(var) : var), "x")); - appendBuffer(scip, file, linebuffer, &linecnt, buffer); - } - appendBuffer(scip, file, linebuffer, &linecnt, " "); - } - - /* print left hand side */ - if( SCIPisZero(scip, lhs) ) - lhs = 0.0; - - (void) SCIPsnprintf(buffer, OPB_MAX_LINELEN, "%s %" SCIP_LONGINT_FORMAT " ;\n", type, (SCIP_Longint) (lhs * (*mult)) ); - appendBuffer(scip, file, linebuffer, &linecnt, buffer); - - writeBuffer(scip, file, linebuffer, &linecnt); - - return SCIP_OKAY; -} - - -/** prints given pseudo boolean constraint information in OPB format to file stream */ -static -SCIP_RETCODE printPseudobooleanCons( - SCIP*const scip, /**< SCIP data structure */ - FILE*const file, /**< output file, or NULL if standard output should be used */ - SCIP_VAR**const linvars, /**< array with variables of linear part */ - SCIP_Real*const linvals, /**< array of coefficients values of linear part */ - int const nlinvars, /**< number variables in linear part of the problem */ - SCIP_VAR***const termvars, /**< term array with array of variables to print */ - int*const ntermvars, /**< array with number of variables in each term */ - SCIP_Real*const termvals, /**< array of coefficient values for non-linear variables */ - int const ntermvals, /**< number non-linear variables in the problem */ - SCIP_VAR*const indvar, /**< indicator variable, or NULL */ - SCIP_Real const lhs, /**< left hand side of constraint */ - SCIP_Real const rhs, /**< right hand side of constraint */ - SCIP_Bool transformed, /**< should the transformed problem be printed ? */ - const char* multisymbol /**< the multiplication symbol to use between coefficient and variable */ - ) -{ - SCIP_VAR*** activetermvars; - SCIP_Bool** negatedarrays; - SCIP_VAR** activelinvars; - SCIP_Real* activelinvals; - int nactivelinvars; - SCIP_Real activelinconstant; - SCIP_Longint mult; - SCIP_RETCODE retcode; - int v; - - assert(scip != NULL); - assert(linvars != NULL || nlinvars == 0); - assert(linvals != NULL || nlinvars == 0); - assert(termvars != NULL || 0 == ntermvals); - assert(ntermvars != NULL || 0 == ntermvals); - assert(termvals != NULL || 0 == ntermvals); - assert(lhs <= rhs); - - if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) ) - return SCIP_OKAY; - - activelinconstant = 0.0; - - /* duplicate variable and value array for linear part */ - nactivelinvars = nlinvars; - if( nactivelinvars > 0 ) - { - SCIP_CALL( SCIPduplicateBufferArray(scip, &activelinvars, linvars, nactivelinvars ) ); - SCIP_CALL( SCIPduplicateBufferArray(scip, &activelinvals, linvals, nactivelinvars ) ); - - /* retransform given variables to active variables */ - SCIP_CALL( getActiveVariables(scip, activelinvars, activelinvals, &nactivelinvars, &activelinconstant, transformed) ); - } - else - { - activelinvars = NULL; - activelinvals = NULL; - } - - /* create non-linear information for printing */ - if( ntermvals > 0 ) - { - assert(termvars != NULL); - assert(ntermvars != NULL); - assert(termvals != NULL); - - SCIP_CALL( SCIPallocBufferArray(scip, &activetermvars, ntermvals) ); - SCIP_CALL( SCIPallocBufferArray(scip, &negatedarrays, ntermvals) ); - for( v = ntermvals - 1; v >= 0; --v ) - { - assert(ntermvars[v] > 0); /*lint !e613 */ - - if( transformed ) - { - SCIP_CALL( SCIPallocBufferArray(scip, &(activetermvars[v]), ntermvars[v]) ); /*lint !e866 */ - SCIP_CALL( SCIPallocBufferArray(scip, &(negatedarrays[v]), ntermvars[v]) ); /*lint !e866 */ - - /* get binary representatives of binary variables in non-linear terms */ - SCIP_CALL( SCIPgetBinvarRepresentatives(scip, ntermvars[v], termvars[v], activetermvars[v], negatedarrays[v]) ); - } - else - { - SCIP_CALL( SCIPduplicateBufferArray(scip, &(activetermvars[v]), termvars[v], ntermvars[v]) ); /*lint !e866 */ - SCIP_CALL( SCIPallocBufferArray(scip, &(negatedarrays[v]), ntermvars[v]) ); /*lint !e866 */ - BMSclearMemoryArray(negatedarrays[v], ntermvars[v]); /*lint !e866 */ - } - } - } - else - { - activetermvars = NULL; - negatedarrays = NULL; - } - - mult = 1; - retcode = SCIP_OKAY; - - /* print row(s) in OPB format */ - if( SCIPisEQ(scip, lhs, rhs) ) - { - assert( !SCIPisInfinity(scip, rhs) ); - - /* equality constraint */ - retcode = printPBRow(scip, file, "=", activelinvars, activelinvals, nactivelinvars, activetermvars, - ntermvars, termvals, ntermvals, negatedarrays, indvar, rhs - activelinconstant, &mult, multisymbol); - } - else - { - if( !SCIPisInfinity(scip, -lhs) ) - { - /* print inequality ">=" */ - retcode = printPBRow(scip, file, ">=", activelinvars, activelinvals, nactivelinvars, activetermvars, - ntermvars, termvals, ntermvals, negatedarrays, indvar, lhs - activelinconstant, &mult, multisymbol); - } - - if( !SCIPisInfinity(scip, rhs) ) - { - mult *= -1; - - /* print inequality ">=" and multiplying all coefficients by -1 */ - /* coverity[var_deref_model] */ - retcode = printPBRow(scip, file, ">=", activelinvars, activelinvals, nactivelinvars, activetermvars, - ntermvars, termvals, ntermvals, negatedarrays, indvar, rhs - activelinconstant, &mult, multisymbol); - } - } - - /* free buffers for non-linear arrays */ - if( ntermvals > 0 ) - { - assert(negatedarrays != NULL); - assert(activetermvars != NULL); - - for( v = 0; v < ntermvals; ++v ) - { - assert(negatedarrays[v] != NULL); - assert(activetermvars[v] != NULL); - SCIPfreeBufferArray(scip, &(negatedarrays[v])); - SCIPfreeBufferArray(scip, &(activetermvars[v])); - } - SCIPfreeBufferArray(scip, &negatedarrays); - SCIPfreeBufferArray(scip, &activetermvars); - } - - /* free buffer for linear arrays */ - if( nactivelinvars > 0 ) - { - SCIPfreeBufferArray(scip, &activelinvals); - SCIPfreeBufferArray(scip, &activelinvars); - } - - return retcode; -} - -/** determine total number of linear constraints split into lhs/rhs */ +/** determine total number of split linear and indicator constraints */ static void determineTotalNumberLinearConss( SCIP*const scip, /**< SCIP data structure */ SCIP_CONS**const conss, /**< array with constraints of the problem */ int const nconss, /**< number of constraints in the problem */ - int* nlinearconss, /**< pointer to store the total number of linear constraints */ - int* nsplitlinearconss /**< pointer to store the total number of linear constraints split into lhs/rhs */ + int* nlinearconss, /**< pointer to store the total number of split linear constraints */ + int* nindicatorconss /**< pointer to store the total number of indicator constraints */ ) { SCIP_CONSHDLR* conshdlr; @@ -3279,14 +2991,18 @@ void determineTotalNumberLinearConss( assert(scip != NULL); assert(conss != NULL || nconss == 0); assert(nlinearconss != NULL); - assert(nsplitlinearconss != NULL); + assert(nindicatorconss != NULL); *nlinearconss = 0; - *nsplitlinearconss = 0; + *nindicatorconss = 0; /* loop over all constraints */ for( c = 0; c < nconss; ++c ) { + SCIP_Real lhs; + SCIP_Real rhs; + SCIP_Bool success; + cons = conss[c]; assert(cons != NULL); conshdlr = SCIPconsGetHdlr(cons); /*lint !e613*/ @@ -3294,26 +3010,43 @@ void determineTotalNumberLinearConss( conshdlrname = SCIPconshdlrGetName(conshdlr); - if( strcmp(conshdlrname, "linear") == 0 ) - { - if( ! SCIPisInfinity(scip, SCIPgetLhsLinear(scip, cons)) ) - ++(*nsplitlinearconss); + if( strcmp(conshdlrname, "and") == 0 ) + continue; - if( ! SCIPisInfinity(scip, SCIPgetRhsLinear(scip, cons)) ) - ++(*nsplitlinearconss); + if( strcmp(conshdlrname, "pseudoboolean") == 0 ) + { + if( SCIPgetIndVarPseudoboolean(scip, cons) != NULL ) + ++(*nindicatorconss); - ++(*nlinearconss); + continue; } - if( strcmp(conshdlrname, "varbound") == 0 ) + if( strcmp(conshdlrname, "indicator") == 0 ) { - if( ! SCIPisInfinity(scip, SCIPgetLhsVarbound(scip, cons)) ) - ++(*nsplitlinearconss); + ++(*nindicatorconss); + + continue; + } - if( ! SCIPisInfinity(scip, SCIPgetRhsVarbound(scip, cons)) ) - ++(*nsplitlinearconss); + lhs = SCIPconsGetLhs(scip, cons, &success); + if( !success ) + continue; + + rhs = SCIPconsGetRhs(scip, cons, &success); + + if( !success ) + continue; + + if( SCIPisEQ(scip, lhs, rhs) ) ++(*nlinearconss); + else + { + if( !SCIPisInfinity(scip, -lhs) ) + ++(*nlinearconss); + + if( !SCIPisInfinity(scip, rhs) ) + ++(*nlinearconss); } } } @@ -3339,10 +3072,11 @@ SCIP_RETCODE writeOpbConstraints( { SCIP_CONSHDLR* conshdlr; const char* conshdlrname; - SCIP_CONS* cons; + SCIP_CONS* cons = NULL; SCIP_VAR** consvars; SCIP_Real* consvals; - SCIP_RETCODE retcode; + SCIP_Bool topcostfound = FALSE; + SCIP_RETCODE retcode = SCIP_OKAY; int nconsvars; int v, c; SCIP_HASHMAP* linconssofindicatorsmap = NULL; @@ -3363,31 +3097,31 @@ SCIP_RETCODE writeOpbConstraints( /* find artificial linear constraints which correspond to indicator constraints to avoid double printing */ if( conshdlr != NULL ) { - SCIP_CONS** indconss; - int nindconss; - - indconss = SCIPconshdlrGetConss(conshdlr); - nindconss = SCIPconshdlrGetNConss(conshdlr); - assert(indconss != NULL || nindconss == 0); - - if( nindconss > 0 ) - { - SCIP_CONS* lincons; - - /* create the linear constraint of indicator constraints hash map */ - SCIP_CALL( SCIPhashmapCreate(&linconssofindicatorsmap, SCIPblkmem(scip), nindconss) ); - assert(indconss != NULL); - - for( c = 0; c < nindconss; ++c ) - { - assert(indconss[c] != NULL); - lincons = SCIPgetLinearConsIndicator(indconss[c]); - assert(lincons != NULL); - - /* insert constraint into mapping between */ - SCIP_CALL( SCIPhashmapInsert(linconssofindicatorsmap, (void*)lincons, (void*)lincons) ); - } - } + SCIP_CONS** indconss; + int nindconss; + + indconss = SCIPconshdlrGetConss(conshdlr); + nindconss = SCIPconshdlrGetNConss(conshdlr); + assert(indconss != NULL || nindconss == 0); + + if( nindconss > 0 ) + { + SCIP_CONS* lincons; + + /* create the linear constraint of indicator constraints hash map */ + SCIP_CALL( SCIPhashmapCreate(&linconssofindicatorsmap, SCIPblkmem(scip), nindconss) ); + assert(indconss != NULL); + + for( c = 0; c < nindconss; ++c ) + { + assert(indconss[c] != NULL); + lincons = SCIPgetLinearConsIndicator(indconss[c]); + assert(lincons != NULL); + + /* insert constraints into mapping */ + SCIP_CALL( SCIPhashmapInsert(linconssofindicatorsmap, (void*)lincons, (void*)indconss[c]) ); + } + } } conshdlr = SCIPfindConshdlr(scip, "pseudoboolean"); @@ -3395,30 +3129,30 @@ SCIP_RETCODE writeOpbConstraints( /* find artifical linear constraints which correspond to indicator constraints to avoid double printing */ if( conshdlr != NULL ) { - SCIP_CONS** pbconss; - int npbconss; - - pbconss = SCIPconshdlrGetConss(conshdlr); - npbconss = SCIPconshdlrGetNConss(conshdlr); - assert(pbconss != NULL || npbconss == 0); - - if( npbconss > 0 ) - { - SCIP_CONS* lincons; - - /* create the linear constraint of indicator constraints hash map */ - SCIP_CALL( SCIPhashmapCreate(&linconssofpbsmap, SCIPblkmem(scip), npbconss) ); - - for( c = 0; c < npbconss; ++c ) - { - assert(pbconss[c] != NULL); /*lint !e613*/ - lincons = SCIPgetLinearConsPseudoboolean(scip, pbconss[c]); /*lint !e613*/ - assert(lincons != NULL); - - /* insert constraint into mapping between */ - SCIP_CALL( SCIPhashmapInsert(linconssofpbsmap, (void*)lincons, (void*)lincons) ); - } - } + SCIP_CONS** pbconss; + int npbconss; + + pbconss = SCIPconshdlrGetConss(conshdlr); + npbconss = SCIPconshdlrGetNConss(conshdlr); + assert(pbconss != NULL || npbconss == 0); + + if( npbconss > 0 ) + { + SCIP_CONS* lincons; + + /* create the linear constraint of indicator constraints hash map */ + SCIP_CALL( SCIPhashmapCreate(&linconssofpbsmap, SCIPblkmem(scip), npbconss) ); + + for( c = 0; c < npbconss; ++c ) + { + assert(pbconss[c] != NULL); /*lint !e613*/ + lincons = SCIPgetLinearConsPseudoboolean(scip, pbconss[c]); /*lint !e613*/ + assert(lincons != NULL); + + /* insert constraints into mapping */ + SCIP_CALL( SCIPhashmapInsert(linconssofpbsmap, (void*)lincons, (void*)pbconss[c]) ); + } + } } } /* in original space we cannot ask the constraint handler for its constraints, therefore we have to loop over all @@ -3433,53 +3167,50 @@ SCIP_RETCODE writeOpbConstraints( /* loop over all constraint for printing */ for( c = 0; c < nconss; ++c ) { - conshdlr = SCIPconsGetHdlr(conss[c]); /*lint !e613*/ - assert(conshdlr != NULL); - - conshdlrname = SCIPconshdlrGetName(conshdlr); - - if( strcmp(conshdlrname, "pseudoboolean") == 0 ) - { - if( !pbhashmapcreated ) - { - /* create the linear constraint of indicator constraints hash map */ - SCIP_CALL( SCIPhashmapCreate(&linconssofpbsmap, SCIPblkmem(scip), nconss) ); - pbhashmapcreated = TRUE; - } - - lincons = SCIPgetLinearConsPseudoboolean(scip, conss[c]); /*lint !e613*/ - assert(lincons != NULL); - - /* insert constraint into mapping between */ - SCIP_CALL( SCIPhashmapInsert(linconssofpbsmap, (void*)lincons, (void*)lincons) ); - } - else if( strcmp(conshdlrname, "indicator") == 0 ) - { - if( !indhashmapcreated ) - { - /* create the linear constraint of indicator constraints hash map */ - SCIP_CALL( SCIPhashmapCreate(&linconssofindicatorsmap, SCIPblkmem(scip), nconss) ); - indhashmapcreated = TRUE; - } - - lincons = SCIPgetLinearConsIndicator(conss[c]); /*lint !e613*/ - assert(lincons != NULL); - - /* insert constraint into mapping between */ - SCIP_CALL( SCIPhashmapInsert(linconssofindicatorsmap, (void*)lincons, (void*)lincons) ); - } + conshdlr = SCIPconsGetHdlr(conss[c]); /*lint !e613*/ + assert(conshdlr != NULL); + + conshdlrname = SCIPconshdlrGetName(conshdlr); + + if( strcmp(conshdlrname, "pseudoboolean") == 0 ) + { + if( !pbhashmapcreated ) + { + /* create the linear constraint of indicator constraints hash map */ + SCIP_CALL( SCIPhashmapCreate(&linconssofpbsmap, SCIPblkmem(scip), nconss) ); + pbhashmapcreated = TRUE; + } + + lincons = SCIPgetLinearConsPseudoboolean(scip, conss[c]); /*lint !e613*/ + assert(lincons != NULL); + + /* insert constraints into mapping */ + SCIP_CALL( SCIPhashmapInsert(linconssofpbsmap, (void*)lincons, (void*)conss[c]) ); + } + else if( strcmp(conshdlrname, "indicator") == 0 ) + { + if( !indhashmapcreated ) + { + /* create the linear constraint of indicator constraints hash map */ + SCIP_CALL( SCIPhashmapCreate(&linconssofindicatorsmap, SCIPblkmem(scip), nconss) ); + indhashmapcreated = TRUE; + } + + lincons = SCIPgetLinearConsIndicator(conss[c]); /*lint !e613*/ + assert(lincons != NULL); + + /* insert constraint into mapping */ + SCIP_CALL( SCIPhashmapInsert(linconssofindicatorsmap, (void*)lincons, (void*)conss[c]) ); + } } } - retcode = SCIP_OKAY; - cons = NULL; - /* loop over all constraint for printing */ for( c = 0; c < nconss && retcode == SCIP_OKAY; ++c ) { - SCIP_CONS* artcons; - - artcons = NULL; + SCIP_CONS* artcons = NULL; + SCIP_VAR* indvar = NULL; + SCIP_Longint weight = 0LL; cons = conss[c]; /*lint !e613 */ assert(cons != NULL); @@ -3493,340 +3224,334 @@ SCIP_RETCODE writeOpbConstraints( /* in case the transformed is written only constraint are posted which are enabled in the current node */ assert(!transformed || SCIPconsIsEnabled(cons)); + if( linconssofindicatorsmap != NULL ) + { + artcons = (SCIP_CONS*)SCIPhashmapGetImage(linconssofindicatorsmap, (void*)cons); + + if( artcons != NULL ) + continue; + } + if( linconssofpbsmap != NULL ) - artcons = (SCIP_CONS*) SCIPhashmapGetImage(linconssofpbsmap, (void*)cons); - if( artcons == NULL && linconssofindicatorsmap != NULL ) - artcons = (SCIP_CONS*) SCIPhashmapGetImage(linconssofindicatorsmap, (void*)cons); + { + artcons = (SCIP_CONS*)SCIPhashmapGetImage(linconssofpbsmap, (void*)cons); + + if( artcons != NULL ) + { + indvar = SCIPgetIndVarPseudoboolean(scip, artcons); + + if( indvar != NULL ) + { + weight = (SCIP_Longint)SCIPround(scip, SCIPvarGetObj(indvar)); + + if( weight == 0 ) + { + SCIPwarningMessage(scip, "pseudoboolean constraint <%s> will not be printed because its indicator variable has no objective value(= weight of this soft constraint)\n", SCIPconsGetName(artcons)); + SCIPinfoMessage(scip, file, "* "); + SCIP_CALL( SCIPprintCons(scip, artcons, file) ); + SCIPinfoMessage(scip, file, ";\n"); + + continue; + } + } + } + } + + /* if we found the topcost linear inequality which gives us the maximal cost which could be violated, + * we can stop printing because it is an artificial constraint + */ + if( strstr(SCIPconsGetName(cons), TOPCOSTCONSNAME) != NULL ) + { + if( topcostfound ) + SCIPwarningMessage(scip, "further topcost constraint <%s> will be considered as hard constraint\n", SCIPconsGetName(cons)); + else + { + topcostfound = TRUE; + + continue; + } + } - if( artcons == NULL ) + if( strcmp(conshdlrname, "linear") == 0 ) { - if( strcmp(conshdlrname, "linear") == 0 ) - { - if( existands ) - { - retcode = printNonLinearCons(scip, file, + if( existands ) + { + retcode = printNonLinearCons(scip, file, SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons), SCIPgetNVarsLinear(scip, cons), SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), resvars, nresvars, andvars, nandvars, - 0LL, transformed, multisymbol); - } - else - { - retcode = printLinearCons(scip, file, + weight, transformed, multisymbol); + } + else + { + retcode = printLinearCons(scip, file, SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons), SCIPgetNVarsLinear(scip, cons), - SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), 0LL, transformed, multisymbol); - } - } - else if( strcmp(conshdlrname, "setppc") == 0 ) - { - consvars = SCIPgetVarsSetppc(scip, cons); - nconsvars = SCIPgetNVarsSetppc(scip, cons); - - switch( SCIPgetTypeSetppc(scip, cons) ) - { - case SCIP_SETPPCTYPE_PARTITIONING : - if( existands ) - { - retcode = printNonLinearCons(scip, file, consvars, NULL, nconsvars, 1.0, 1.0, resvars, nresvars, - andvars, nandvars, 0LL, transformed, multisymbol); - } - else - { - retcode = printLinearCons(scip, file, - consvars, NULL, nconsvars, 1.0, 1.0, 0LL, transformed, multisymbol); - } - break; - case SCIP_SETPPCTYPE_PACKING : - if( existands ) - { - retcode = printNonLinearCons(scip, file, + SCIPgetLhsLinear(scip, cons), SCIPgetRhsLinear(scip, cons), weight, transformed, multisymbol); + } + } + else if( strcmp(conshdlrname, "setppc") == 0 ) + { + consvars = SCIPgetVarsSetppc(scip, cons); + nconsvars = SCIPgetNVarsSetppc(scip, cons); + + switch( SCIPgetTypeSetppc(scip, cons) ) + { + case SCIP_SETPPCTYPE_PARTITIONING : + if( existands ) + { + retcode = printNonLinearCons(scip, file, consvars, NULL, nconsvars, 1.0, 1.0, resvars, nresvars, + andvars, nandvars, weight, transformed, multisymbol); + } + else + { + retcode = printLinearCons(scip, file, + consvars, NULL, nconsvars, 1.0, 1.0, weight, transformed, multisymbol); + } + break; + case SCIP_SETPPCTYPE_PACKING : + if( existands ) + { + retcode = printNonLinearCons(scip, file, consvars, NULL, nconsvars, -SCIPinfinity(scip), 1.0, resvars, nresvars, andvars, nandvars, - 0LL, transformed, multisymbol); - } - else - { - retcode = printLinearCons(scip, file, - consvars, NULL, nconsvars, -SCIPinfinity(scip), 1.0, 0LL, transformed, multisymbol); - } - break; - case SCIP_SETPPCTYPE_COVERING : - if( existands ) - { - retcode = printNonLinearCons(scip, file, + weight, transformed, multisymbol); + } + else + { + retcode = printLinearCons(scip, file, + consvars, NULL, nconsvars, -SCIPinfinity(scip), 1.0, weight, transformed, multisymbol); + } + break; + case SCIP_SETPPCTYPE_COVERING : + if( existands ) + { + retcode = printNonLinearCons(scip, file, consvars, NULL, nconsvars, 1.0, SCIPinfinity(scip), resvars, nresvars, andvars, nandvars, - 0LL, transformed, multisymbol); - } - else - { - retcode = printLinearCons(scip, file, - consvars, NULL, nconsvars, 1.0, SCIPinfinity(scip), 0LL, transformed, multisymbol); - } - break; - } - } - else if( strcmp(conshdlrname, "logicor") == 0 ) - { - if( existands ) - { - retcode = printNonLinearCons(scip, file, + weight, transformed, multisymbol); + } + else + { + retcode = printLinearCons(scip, file, + consvars, NULL, nconsvars, 1.0, SCIPinfinity(scip), weight, transformed, multisymbol); + } + break; + } + } + else if( strcmp(conshdlrname, "logicor") == 0 ) + { + if( existands ) + { + retcode = printNonLinearCons(scip, file, SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons), 1.0, SCIPinfinity(scip), - resvars, nresvars, andvars, nandvars, 0LL, transformed, multisymbol); - } - else - { - retcode = printLinearCons(scip, file, + resvars, nresvars, andvars, nandvars, weight, transformed, multisymbol); + } + else + { + retcode = printLinearCons(scip, file, SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons), - 1.0, SCIPinfinity(scip), 0LL, transformed, multisymbol); - } - } - else if( strcmp(conshdlrname, "knapsack") == 0 ) - { - SCIP_Longint* weights; - - consvars = SCIPgetVarsKnapsack(scip, cons); - nconsvars = SCIPgetNVarsKnapsack(scip, cons); - - /* copy Longint array to SCIP_Real array */ - weights = SCIPgetWeightsKnapsack(scip, cons); - SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) ); - for( v = 0; v < nconsvars; ++v ) - consvals[v] = (SCIP_Real)weights[v]; - - if( existands ) - { - retcode = printNonLinearCons(scip, file, consvars, consvals, nconsvars, -SCIPinfinity(scip), + 1.0, SCIPinfinity(scip), weight, transformed, multisymbol); + } + } + else if( strcmp(conshdlrname, "knapsack") == 0 ) + { + SCIP_Longint* weights; + + consvars = SCIPgetVarsKnapsack(scip, cons); + nconsvars = SCIPgetNVarsKnapsack(scip, cons); + + /* copy Longint array to SCIP_Real array */ + weights = SCIPgetWeightsKnapsack(scip, cons); + SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) ); + for( v = 0; v < nconsvars; ++v ) + consvals[v] = (SCIP_Real)weights[v]; + + if( existands ) + { + retcode = printNonLinearCons(scip, file, consvars, consvals, nconsvars, -SCIPinfinity(scip), (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), resvars, nresvars, andvars, nandvars, - 0LL, transformed, multisymbol); - } - else - { - retcode = printLinearCons(scip, file, consvars, consvals, nconsvars, -SCIPinfinity(scip), - (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), 0LL, transformed, multisymbol); - } - - SCIPfreeBufferArray(scip, &consvals); - } - else if( strcmp(conshdlrname, "varbound") == 0 ) - { - SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) ); - SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) ); - - consvars[0] = SCIPgetVarVarbound(scip, cons); - consvars[1] = SCIPgetVbdvarVarbound(scip, cons); - - consvals[0] = 1.0; - consvals[1] = SCIPgetVbdcoefVarbound(scip, cons); - - if( existands ) - { - retcode = printNonLinearCons(scip, file, consvars, consvals, 2, SCIPgetLhsVarbound(scip, cons), - SCIPgetRhsVarbound(scip, cons), resvars, nresvars, andvars, nandvars, 0LL, transformed, multisymbol); - } - else - { - retcode = printLinearCons(scip, file, consvars, consvals, 2, SCIPgetLhsVarbound(scip, cons), - SCIPgetRhsVarbound(scip, cons), 0LL, transformed, multisymbol); - } - - SCIPfreeBufferArray(scip, &consvals); - SCIPfreeBufferArray(scip, &consvars); - } - else if( strcmp(conshdlrname, "pseudoboolean") == 0 ) - { - SCIP_VAR*** termvars; - int* ntermvars; - int termvarssize; - SCIP_CONS** andconss; - SCIP_Real* andcoefs ; - SCIP_VAR** linvars; - SCIP_Real* lincoefs ; - int nlinvars; - int t; - - /* get the required array size for the variables array and for the number of variables in each variable array */ - termvarssize = SCIPgetNAndsPseudoboolean(scip, cons); - assert(termvarssize >= 0); - - /* allocate temporary memory */ - SCIP_CALL( SCIPallocBufferArray(scip, &andconss, termvarssize) ); - SCIP_CALL( SCIPallocBufferArray(scip, &termvars, termvarssize) ); - SCIP_CALL( SCIPallocBufferArray(scip, &andcoefs, termvarssize) ); - SCIP_CALL( SCIPallocBufferArray(scip, &ntermvars, termvarssize) ); - - /* get all corresponding and-constraints and therefor all variables */ - SCIP_CALL( SCIPgetAndDatasPseudoboolean(scip, cons, andconss, andcoefs, &termvarssize) ); - for( t = termvarssize - 1; t >= 0; --t ) - { - termvars[t] = SCIPgetVarsAnd(scip, andconss[t]); - ntermvars[t] = SCIPgetNVarsAnd(scip, andconss[t]); - } - - /* gets number of linear variables without artificial terms variables of pseudoboolean constraint */ - nlinvars = SCIPgetNLinVarsWithoutAndPseudoboolean(scip, cons); - - /* allocate temporary memory */ - SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nlinvars) ); - SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nlinvars) ); - - /* gets linear constraint of pseudoboolean constraint */ - SCIP_CALL( SCIPgetLinDatasWithoutAndPseudoboolean(scip, cons, linvars, lincoefs, &nlinvars) ); - - retcode = printPseudobooleanCons(scip, file, linvars, lincoefs, nlinvars, - termvars, ntermvars, andcoefs, termvarssize, SCIPgetIndVarPseudoboolean(scip, cons), - SCIPgetLhsPseudoboolean(scip, cons), SCIPgetRhsPseudoboolean(scip, cons), transformed, multisymbol); - - /* free temporary memory */ - SCIPfreeBufferArray(scip, &lincoefs); - SCIPfreeBufferArray(scip, &linvars); - SCIPfreeBufferArray(scip, &ntermvars); - SCIPfreeBufferArray(scip, &andcoefs); - SCIPfreeBufferArray(scip, &termvars); - SCIPfreeBufferArray(scip, &andconss); - } - else if( strcmp(conshdlrname, "indicator") == 0 ) - { - SCIP_CONS* lincons; - SCIP_VAR* indvar; - SCIP_VAR* slackvar; - SCIP_Longint weight; - - /* get artificial binary indicator variables */ - indvar = SCIPgetBinaryVarIndicator(cons); - assert(indvar != NULL); - - if( SCIPvarGetStatus(indvar) == SCIP_VARSTATUS_NEGATED ) - { - indvar = SCIPvarGetNegationVar(indvar); - assert(indvar != NULL); - assert(SCIPvarGetStatus(indvar) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(indvar) != SCIP_VARSTATUS_MULTAGGR); - - /* get the soft cost of this constraint */ - weight = (SCIP_Longint) SCIPvarGetObj(indvar); - } - else - { - assert(SCIPvarGetStatus(indvar) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(indvar) != SCIP_VARSTATUS_MULTAGGR); - - /* get the soft cost of this constraint */ - weight = -(SCIP_Longint) SCIPvarGetObj(indvar); - } - - /* get artificial slack variable */ - slackvar = SCIPgetSlackVarIndicator(cons); - assert(slackvar != NULL); - - /* only need to print indicator constraints with weights on their indicator variable */ - if( weight != 0 ) - { - SCIP_VAR** scipvarslinear; - SCIP_Real* scipvalslinear; - SCIP_Bool cont; - int nonbinarypos; - - lincons = SCIPgetLinearConsIndicator(cons); - assert(lincons != NULL); - - nconsvars = SCIPgetNVarsLinear(scip, lincons); - scipvarslinear = SCIPgetVarsLinear(scip, lincons); - scipvalslinear = SCIPgetValsLinear(scip, lincons); - - /* allocate temporary memory */ - SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, scipvarslinear, nconsvars) ); - SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, scipvalslinear, nconsvars) ); - - nonbinarypos = -1; - cont = FALSE; - - /* find non-binary variable */ - for( v = 0; v < nconsvars; ++v ) - { - if( SCIPvarGetType(consvars[v]) != SCIP_VARTYPE_BINARY ) - { - if( consvars[v] == slackvar ) - { - assert(nonbinarypos == -1); - nonbinarypos = v; - } - else - { - SCIPwarningMessage(scip, "cannot print linear constraint <%s> of indicator constraint <%s> because it has more than one non-binary variable\n", SCIPconsGetName(lincons), SCIPconsGetName(cons) ); - SCIPinfoMessage(scip, file, "* "); - SCIP_CALL( SCIPprintCons(scip, cons, file) ); - SCIPinfoMessage(scip, file, ";\n"); - cont = TRUE; - break; - } - } - } - - /* if we have not found any non-binary variable we do not print the constraint, maybe we should ??? */ - if( nonbinarypos == -1 ) - { - SCIPwarningMessage(scip, "cannot print linear constraint <%s> of indicator constraint <%s> because it has no slack variable\n", SCIPconsGetName(lincons), SCIPconsGetName(cons) ); - SCIPinfoMessage(scip, file, "* "); - SCIP_CALL( SCIPprintCons(scip, cons, file) ); - SCIPinfoMessage(scip, file, ";\n"); - - /* free temporary memory */ - SCIPfreeBufferArray(scip, &consvals); - SCIPfreeBufferArray(scip, &consvars); - continue; - } - - /* if the constraint has more than two non-binary variables is not printable and we go to the next */ - if( cont ) - { - /* free temporary memory */ - SCIPfreeBufferArray(scip, &consvals); - SCIPfreeBufferArray(scip, &consvars); - continue; - } - - assert(0 <= nonbinarypos && nonbinarypos < nconsvars); - - /* remove slackvariable in linear constraint for printing */ - --nconsvars; - consvars[nonbinarypos] = consvars[nconsvars]; - consvals[nonbinarypos] = consvals[nconsvars]; - - if( existands ) - { - retcode = printNonLinearCons(scip, file, + weight, transformed, multisymbol); + } + else + { + retcode = printLinearCons(scip, file, consvars, consvals, nconsvars, -SCIPinfinity(scip), + (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons), weight, transformed, multisymbol); + } + + SCIPfreeBufferArray(scip, &consvals); + } + else if( strcmp(conshdlrname, "varbound") == 0 ) + { + SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) ); + SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) ); + + consvars[0] = SCIPgetVarVarbound(scip, cons); + consvars[1] = SCIPgetVbdvarVarbound(scip, cons); + + consvals[0] = 1.0; + consvals[1] = SCIPgetVbdcoefVarbound(scip, cons); + + if( existands ) + { + retcode = printNonLinearCons(scip, file, consvars, consvals, 2, SCIPgetLhsVarbound(scip, cons), + SCIPgetRhsVarbound(scip, cons), resvars, nresvars, andvars, nandvars, weight, transformed, multisymbol); + } + else + { + retcode = printLinearCons(scip, file, consvars, consvals, 2, SCIPgetLhsVarbound(scip, cons), + SCIPgetRhsVarbound(scip, cons), weight, transformed, multisymbol); + } + + SCIPfreeBufferArray(scip, &consvals); + SCIPfreeBufferArray(scip, &consvars); + } + else if( strcmp(conshdlrname, "indicator") == 0 ) + { + SCIP_CONS* lincons; + SCIP_VAR* slackvar; + + /* get artificial binary indicator variables */ + indvar = SCIPgetBinaryVarIndicator(cons); + assert(indvar != NULL); + + if( SCIPvarGetStatus(indvar) == SCIP_VARSTATUS_NEGATED ) + { + indvar = SCIPvarGetNegationVar(indvar); + assert(indvar != NULL); + assert(SCIPvarGetStatus(indvar) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(indvar) != SCIP_VARSTATUS_MULTAGGR); + + /* get the soft cost of this constraint */ + weight = (SCIP_Longint)SCIPround(scip, SCIPvarGetObj(indvar)); + } + else + { + assert(SCIPvarGetStatus(indvar) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(indvar) != SCIP_VARSTATUS_MULTAGGR); + + /* get the soft cost of this constraint */ + weight = (SCIP_Longint)SCIPround(scip, -SCIPvarGetObj(indvar)); + } + + /* get artificial slack variable */ + slackvar = SCIPgetSlackVarIndicator(cons); + assert(slackvar != NULL); + + /* only need to print indicator constraints with weights on their indicator variable */ + if( weight != 0 ) + { + SCIP_VAR** scipvarslinear; + SCIP_Real* scipvalslinear; + SCIP_Bool cont; + int nonbinarypos; + + lincons = SCIPgetLinearConsIndicator(cons); + assert(lincons != NULL); + + nconsvars = SCIPgetNVarsLinear(scip, lincons); + scipvarslinear = SCIPgetVarsLinear(scip, lincons); + scipvalslinear = SCIPgetValsLinear(scip, lincons); + + /* allocate temporary memory */ + SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, scipvarslinear, nconsvars) ); + SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, scipvalslinear, nconsvars) ); + + nonbinarypos = -1; + cont = FALSE; + + /* find non-binary variable */ + for( v = 0; v < nconsvars; ++v ) + { + if( SCIPvarGetType(consvars[v]) != SCIP_VARTYPE_BINARY ) + { + if( consvars[v] == slackvar ) + { + assert(nonbinarypos == -1); + nonbinarypos = v; + } + else + { + SCIPwarningMessage(scip, "cannot print linear constraint <%s> of indicator constraint <%s> because it has more than one non-binary variable\n", SCIPconsGetName(lincons), SCIPconsGetName(cons) ); + SCIPinfoMessage(scip, file, "* "); + SCIP_CALL( SCIPprintCons(scip, cons, file) ); + SCIPinfoMessage(scip, file, ";\n"); + cont = TRUE; + break; + } + } + } + + /* if we have not found any non-binary variable we do not print the constraint, maybe we should ??? */ + if( nonbinarypos == -1 ) + { + SCIPwarningMessage(scip, "cannot print linear constraint <%s> of indicator constraint <%s> because it has no slack variable\n", SCIPconsGetName(lincons), SCIPconsGetName(cons) ); + SCIPinfoMessage(scip, file, "* "); + SCIP_CALL( SCIPprintCons(scip, cons, file) ); + SCIPinfoMessage(scip, file, ";\n"); + + /* free temporary memory */ + SCIPfreeBufferArray(scip, &consvals); + SCIPfreeBufferArray(scip, &consvars); + continue; + } + + /* if the constraint has more than two non-binary variables is not printable and we go to the next */ + if( cont ) + { + /* free temporary memory */ + SCIPfreeBufferArray(scip, &consvals); + SCIPfreeBufferArray(scip, &consvars); + continue; + } + + assert(0 <= nonbinarypos && nonbinarypos < nconsvars); + + /* remove slackvariable in linear constraint for printing */ + --nconsvars; + consvars[nonbinarypos] = consvars[nconsvars]; + consvals[nonbinarypos] = consvals[nconsvars]; + + if( existands ) + { + retcode = printNonLinearCons(scip, file, consvars, consvals, nconsvars, SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons), resvars, nresvars, andvars, nandvars, weight, transformed, multisymbol); - } - else - { - retcode = printLinearCons(scip, file, + } + else + { + retcode = printLinearCons(scip, file, consvars, consvals, nconsvars, SCIPgetLhsLinear(scip, lincons), SCIPgetRhsLinear(scip, lincons), weight, transformed, multisymbol); - } - - /* free temporary memory */ - SCIPfreeBufferArray(scip, &consvals); - SCIPfreeBufferArray(scip, &consvars); - } - else - { - SCIPwarningMessage(scip, "indicator constraint <%s> will not be printed because the indicator variable has no objective value(= weight of this soft constraint)\n", SCIPconsGetName(cons) ); - SCIPinfoMessage(scip, file, "* "); - SCIP_CALL( SCIPprintCons(scip, cons, file) ); - SCIPinfoMessage(scip, file, ";\n"); - } - } - else if( strcmp(conshdlrname, "and") == 0 ) - { - /* all resultants of the and constraint will be replaced by all corresponding variables of this constraint, - * so no and-constraint will be printed directly */ - assert(existandconshdlr); - } - else - { - SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname ); - SCIPinfoMessage(scip, file, "* "); - SCIP_CALL( SCIPprintCons(scip, cons, file) ); - SCIPinfoMessage(scip, file, ";\n"); - } + } + + /* free temporary memory */ + SCIPfreeBufferArray(scip, &consvals); + SCIPfreeBufferArray(scip, &consvars); + } + else + { + SCIPwarningMessage(scip, "indicator constraint <%s> will not be printed because the indicator variable has no objective value(= weight of this soft constraint)\n", SCIPconsGetName(cons) ); + SCIPinfoMessage(scip, file, "* "); + SCIP_CALL( SCIPprintCons(scip, cons, file) ); + SCIPinfoMessage(scip, file, ";\n"); + } + } + else if( strcmp(conshdlrname, "and") == 0 ) + { + /* all resultants of the and constraint will be replaced by all corresponding variables of this constraint, + * so no and-constraint will be printed directly + */ + assert(existandconshdlr); + } + else if( strcmp(conshdlrname, "pseudoboolean") == 0 ) + { + /* all and-resultants in linear constraints will be replaced by the corresponding variable products, + * so no pseudoboolean constraint will be printed directly + */ + assert(existands); + } + else + { + SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname ); + SCIPinfoMessage(scip, file, "* "); + SCIP_CALL( SCIPprintCons(scip, cons, file) ); + SCIPinfoMessage(scip, file, ";\n"); } } @@ -3835,7 +3560,7 @@ SCIP_RETCODE writeOpbConstraints( assert(cons != NULL); SCIPerrorMessage("Cannot print constraint %s with non-integral coefficient or sides in opb-format\n", - SCIPconsGetName(cons)); + SCIPconsGetName(cons)); SCIP_CALL( SCIPprintCons(scip, cons, stderr) ); SCIPinfoMessage(scip, file, ";\n"); } @@ -4003,7 +3728,7 @@ SCIP_RETCODE writeOpbRelevantAnds( for( v = nandvars[r] - 1; v >= 0; --v ) /*lint !e613 */ { assert( andvars[r] != NULL ); - assert( andvars[r][v] != NULL ); + assert( andvars[r][v] != NULL ); if( transformed ) { @@ -4054,16 +3779,16 @@ SCIP_RETCODE writeOpbRelevantAnds( * constraint because all other variables are free */ for( v = nandvars[r] - 1; v >= 0; --v ) /*lint !e613 */ - { + { assert( andvars[r] != NULL ); - assert( andvars[r][v] != NULL ); + assert( andvars[r][v] != NULL ); if( SCIPvarGetUbLocal(andvars[r][v]) < 0.5 ) /*lint !e613 */ { cont = TRUE; break; } - } + } if( cont ) continue; @@ -4080,16 +3805,16 @@ SCIP_RETCODE writeOpbRelevantAnds( /* if all variables are already fixed to one, we do not need to print this and constraint */ for( v = nandvars[r] - 1; v >= 0; --v ) - { + { assert( andvars[r] != NULL ); - assert( andvars[r][v] != NULL ); + assert( andvars[r][v] != NULL ); if( SCIPvarGetLbLocal(andvars[r][v]) < 0.5 ) /*lint !e613 */ { cont = FALSE; break; - } - } + } + } if( cont ) continue; @@ -4222,7 +3947,7 @@ SCIP_RETCODE writeOpb( SCIP_Bool usesymbol; SCIP_RETCODE retcode; int nlinearconss; - int nsplitlinearconss; + int nindicatorconss; assert( scip != NULL ); assert( vars != NULL || nvars == 0 ); @@ -4233,14 +3958,14 @@ SCIP_RETCODE writeOpb( SCIP_CALL( SCIPgetBoolParam(scip, "reading/" READER_NAME "/multisymbol", &usesymbol) ); (void) SCIPsnprintf(multisymbol, OPB_MAX_LINELEN, "%s", usesymbol ? " * " : " "); - /* determine how many linear constraints are split */ - determineTotalNumberLinearConss(scip, conss, nconss, &nlinearconss, &nsplitlinearconss); + /* determine how many split linear and indicator constraints exist */ + determineTotalNumberLinearConss(scip, conss, nconss, &nlinearconss, &nindicatorconss); /* print statistics as comment to file */ SCIPinfoMessage(scip, file, "* SCIP STATISTICS\n"); SCIPinfoMessage(scip, file, "* Problem name : %s\n", name); - SCIPinfoMessage(scip, file, "* Variables : %d (all binary)\n", nvars); - SCIPinfoMessage(scip, file, "* Constraints : %d\n", nconss - nlinearconss + nsplitlinearconss); + SCIPinfoMessage(scip, file, "* Variables : %d\n", nvars - nresvars - nindicatorconss); + SCIPinfoMessage(scip, file, "* Constraints : %d\n", nlinearconss); /* create a hash table */ SCIP_CALL( SCIPhashtableCreate(&printedfixing, SCIPblkmem(scip), nvars, @@ -4378,28 +4103,28 @@ SCIP_RETCODE SCIPwriteOpb( SCIP_RESULT* result /**< pointer to store the result of the file writing call */ ) { /*lint --e{715}*/ + SCIP_VAR*** andvars; + SCIP_VAR** resvars; + SCIP_Bool existands; + SCIP_Bool existandconshdlr; SCIP_RETCODE retcode = SCIP_OKAY; + int* nandvars; + int nresvars; + int v; + SCIP_CONSHDLR* indicatorhdlr = SCIPfindConshdlr(scip, "indicator"); + int nindicatorconss = indicatorhdlr != NULL ? SCIPconshdlrGetNConss(indicatorhdlr) : 0; + + /* computes all and-resultants and their corresponding constraint variables */ + /* coverity[leaked_storage] */ + SCIP_CALL( computeAndConstraintInfos(scip, transformed, &resvars, &nresvars, &andvars, &nandvars, &existandconshdlr, &existands) ); - if( nvars != nbinvars && (nintvars > 0 || SCIPfindConshdlr(scip, "indicator") != NULL - || ncontvars + nimplvars != SCIPconshdlrGetNConss(SCIPfindConshdlr(scip, "indicator"))) ) + if( nintvars > 0 || ncontvars + nimplvars > nindicatorconss + nresvars ) { SCIPwarningMessage(scip, "only binary problems can be written in OPB format.\n"); *result = SCIP_DIDNOTRUN; } else { - SCIP_VAR*** andvars; - SCIP_VAR** resvars; - int* nandvars; - SCIP_Bool existands; - SCIP_Bool existandconshdlr; - int nresvars; - int v; - - /* computes all and-resultants and their corresponding constraint variables */ - /* coverity[leaked_storage] */ - SCIP_CALL( computeAndConstraintInfos(scip, transformed, &resvars, &nresvars, &andvars, &nandvars, &existandconshdlr, &existands) ); - if( genericnames ) { #ifndef NDEBUG @@ -4503,24 +4228,25 @@ SCIP_RETCODE SCIPwriteOpb( } } - if( existands ) - { - /* free temporary buffers */ - assert(resvars != NULL); - assert(andvars != NULL); - assert(nandvars != NULL); + *result = SCIP_SUCCESS; + } - for( v = nresvars - 1; v >= 0; --v ) - { - assert(andvars[v] != NULL); - SCIPfreeMemoryArray(scip, &andvars[v]); - } - SCIPfreeMemoryArray(scip, &nandvars); - SCIPfreeMemoryArray(scip, &andvars); - SCIPfreeMemoryArray(scip, &resvars); + if( existands ) + { + /* free temporary buffers */ + assert(resvars != NULL); + assert(andvars != NULL); + assert(nandvars != NULL); + + for( v = nresvars - 1; v >= 0; --v ) + { + assert(andvars[v] != NULL); + SCIPfreeMemoryArray(scip, &andvars[v]); } - *result = SCIP_SUCCESS; + SCIPfreeMemoryArray(scip, &nandvars); + SCIPfreeMemoryArray(scip, &andvars); + SCIPfreeMemoryArray(scip, &resvars); } if( retcode == SCIP_INVALIDDATA )