diff --git a/CHANGELOG b/CHANGELOG index 3b5be34316..5397189402 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -18,6 +18,8 @@ Features Performance improvements ------------------------ +- Reimplemented SCIPvarGetActiveRepresentatives() by using dense arrays to avoid repeated resorting. + Examples and applications ------------------------- @@ -30,6 +32,7 @@ Interface changes ### Deleted and changed API methods +- SCIPgetProbvarLinearSum: remove parameter mergemultiples, which is now automatically true with the new implementation of SCIPvarGetActiveRepresentatives. - SCIPcreateRow*(), SCIPaddVarToRow(), SCIPaddVarsToRow(), SCIPaddVarsToRowSameCoef() can now only be called in the solving stage, because otherwise the LP is not yet available and the row data is invalid. - intvar removed from arguments for SCIPcreateConsPseudobooleanWithConss(), SCIPcreateConsPseudoboolean(), and SCIPcreateConsBasicPseudoboolean() due to dysfunctionality of non-linear objective reformulation with pseudoboolean constraint diff --git a/src/scip/cons_countsols.c b/src/scip/cons_countsols.c index 189024b82b..658727902f 100644 --- a/src/scip/cons_countsols.c +++ b/src/scip/cons_countsols.c @@ -2237,7 +2237,7 @@ SCIP_RETCODE writeExpandedSolutions( nvars = 1; constant = 0.0; - SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, &nvars, nallvars, &constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, &nvars, nallvars, &constant, &requiredsize) ); assert(requiredsize <= nallvars); assert(nvars <= nactivevars); diff --git a/src/scip/cons_linear.c b/src/scip/cons_linear.c index 6078f06637..c6807c0abb 100644 --- a/src/scip/cons_linear.c +++ b/src/scip/cons_linear.c @@ -17938,7 +17938,7 @@ SCIP_RETCODE SCIPcreateConsLinear( SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) ); /* get active variables for new constraint */ - SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize) ); /* if space was not enough we need to resize the buffers */ if( requiredsize > nconsvars ) @@ -17946,7 +17946,7 @@ SCIP_RETCODE SCIPcreateConsLinear( SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) ); - SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize) ); assert(requiredsize <= nconsvars); } @@ -18157,14 +18157,14 @@ SCIP_RETCODE SCIPcopyConsLinear( */ if( !SCIPvarIsOriginal(vars[0]) ) { - SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize) ); if( requiredsize > nvars ) { SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) ); - SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize) ); assert(requiredsize <= nvars); } } @@ -18254,7 +18254,7 @@ SCIP_RETCODE SCIPaddCoefLinear( consvals[0] = val; /* get active variables for new constraint */ - SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize) ); /* if space was not enough we need to resize the buffers */ if( requiredsize > nconsvars ) @@ -18262,7 +18262,7 @@ SCIP_RETCODE SCIPaddCoefLinear( SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) ); - SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize) ); assert(requiredsize <= nconsvars); } diff --git a/src/scip/cons_logicor.c b/src/scip/cons_logicor.c index 3cc0e3c1d1..c3dac02a4c 100644 --- a/src/scip/cons_logicor.c +++ b/src/scip/cons_logicor.c @@ -995,6 +995,7 @@ SCIP_RETCODE applyFixings( SCIP_Bool easycase; int nconsvars; int requiredsize; + int size = 1; int v2; nconsvars = 1; @@ -1004,15 +1005,17 @@ SCIP_RETCODE applyFixings( consvals[0] = 1.0; /* get active variables for new constraint */ - SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize) ); /* if space was not enough we need to resize the buffers */ - if( requiredsize > nconsvars ) + if( requiredsize > size ) { SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) ); + size = requiredsize; - SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) ); - assert(requiredsize <= nconsvars); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize) ); + assert(nconsvars <= size); + assert(requiredsize <= size); } easycase = FALSE; @@ -1057,7 +1060,6 @@ SCIP_RETCODE applyFixings( SCIP_CONS* newcons; SCIP_Real lhs; SCIP_Real rhs; - int size; int k; /* it might happen that there are more than one multi-aggregated variable, so we need to get the whole probvar sum over all variables */ @@ -1080,16 +1082,18 @@ SCIP_RETCODE applyFixings( constant = 0.0; /* get active variables for new constraint */ - SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize) ); /* if space was not enough(we found another multi-aggregation), we need to resize the buffers */ - if( requiredsize > nconsvars ) + if( requiredsize > size ) { SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) ); + size = requiredsize; - SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) ); - assert(requiredsize <= nconsvars); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize) ); + assert(nconsvars <= size); + assert(requiredsize <= size); } lhs = 1.0 - constant; diff --git a/src/scip/cons_pseudoboolean.c b/src/scip/cons_pseudoboolean.c index 95f1c2d4d2..7d33f8ba34 100644 --- a/src/scip/cons_pseudoboolean.c +++ b/src/scip/cons_pseudoboolean.c @@ -5103,7 +5103,7 @@ SCIP_RETCODE correctConshdlrdata( activeconstant = 0.0; nactivevars = 1; SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activescalars, &nactivevars, nvars, - &activeconstant, &requiredsize, TRUE) ); + &activeconstant, &requiredsize) ); assert(requiredsize <= nvars); for( i = 0; i < nactivevars && del; ++i ) @@ -5618,7 +5618,7 @@ SCIP_RETCODE tryUpgradingXor( constant = 0; /* get linear active representation */ - SCIP_CALL( SCIPgetProbvarLinearSum(scip, linvars, lincoefs, &nlinvars, MAXNVARS, &constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, linvars, lincoefs, &nlinvars, MAXNVARS, &constant, &requiredsize) ); SCIP_CALL( SCIPduplicateBufferArray(scip, &activelinvars, linvars, nlinvars) ); if( requiredsize > MAXNVARS ) diff --git a/src/scip/cons_setppc.c b/src/scip/cons_setppc.c index 39bc94434c..6b23ec1a67 100644 --- a/src/scip/cons_setppc.c +++ b/src/scip/cons_setppc.c @@ -1831,25 +1831,28 @@ SCIP_RETCODE applyFixings( SCIP_Bool easycase; int nconsvars; int requiredsize; + int consvarssize = 10; int v2; nconsvars = 1; - SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 1) ); - SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 1) ); + SCIP_CALL( SCIPallocBufferArray(scip, &consvars, consvarssize) ); + SCIP_CALL( SCIPallocBufferArray(scip, &consvals, consvarssize) ); consvars[0] = repvar; consvals[0] = 1.0; /* get active variables for new constraint */ - SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, consvarssize, &constant, &requiredsize) ); /* if space was not enough we need to resize the buffers */ - if( requiredsize > nconsvars ) + if( requiredsize > consvarssize ) { - SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) ); - SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) ); + consvarssize = requiredsize; + SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, consvarssize) ); + SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, consvarssize) ); - SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) ); - assert(requiredsize <= nconsvars); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, consvarssize, &constant, &requiredsize) ); + assert(requiredsize <= consvarssize); } + assert(nconsvars <= consvarssize); easycase = FALSE; @@ -1975,17 +1978,19 @@ SCIP_RETCODE applyFixings( constant = 0.0; /* get active variables for new constraint */ - SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize) ); /* if space was not enough (we found another multi-aggregation), we need to resize the buffers */ - if( requiredsize > nconsvars ) + if( requiredsize > size ) { - SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) ); - SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) ); + size = requiredsize; + SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, size) ); + SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, size) ); - SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) ); - assert(requiredsize <= nconsvars); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize) ); + assert(requiredsize == size); } + assert(nconsvars <= size); /* compute sides */ if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING ) diff --git a/src/scip/cons_sos1.c b/src/scip/cons_sos1.c index 0285023f32..10e0891336 100644 --- a/src/scip/cons_sos1.c +++ b/src/scip/cons_sos1.c @@ -2805,13 +2805,13 @@ SCIP_RETCODE tightenVarsBoundsSOS1( /* transform linear constraint */ constant = 0.0; - SCIP_CALL( SCIPgetProbvarLinearSum(scip, trafolinvars, trafolinvals, &ntrafolinvars, ntrafolinvars, &constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, trafolinvars, trafolinvals, &ntrafolinvars, ntrafolinvars, &constant, &requiredsize) ); if( requiredsize > ntrafolinvars ) { SCIP_CALL( SCIPreallocBufferArray(scip, &trafolinvars, requiredsize + 1) ); SCIP_CALL( SCIPreallocBufferArray(scip, &trafolinvals, requiredsize + 1) ); - SCIP_CALL( SCIPgetProbvarLinearSum(scip, trafolinvars, trafolinvals, &ntrafolinvars, requiredsize, &constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, trafolinvars, trafolinvals, &ntrafolinvars, requiredsize, &constant, &requiredsize) ); assert( requiredsize <= ntrafolinvars ); } if( !SCIPisInfinity(scip, -trafolhs) ) diff --git a/src/scip/expr_var.c b/src/scip/expr_var.c index 8f5c877f16..388121daea 100644 --- a/src/scip/expr_var.c +++ b/src/scip/expr_var.c @@ -104,14 +104,14 @@ SCIP_DECL_EXPRSIMPLIFY(simplifyVar) { int requsize; - SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, coefs, &nvars, varssize, &constant, &requsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, coefs, &nvars, varssize, &constant, &requsize) ); if( requsize > varssize ) { SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requsize) ); varssize = requsize; - SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, coefs, &nvars, varssize, &constant, &requsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, coefs, &nvars, varssize, &constant, &requsize) ); assert(requsize <= nvars); } } diff --git a/src/scip/matrix.c b/src/scip/matrix.c index a9d1080e09..6b4e4cacf0 100644 --- a/src/scip/matrix.c +++ b/src/scip/matrix.c @@ -82,7 +82,7 @@ SCIP_RETCODE getActiveVariables( assert(nvars != NULL); assert(constant != NULL); - SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *nvars, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *nvars, constant, &requiredsize) ); if( requiredsize > *nvars ) { @@ -90,7 +90,7 @@ SCIP_RETCODE getActiveVariables( SCIP_CALL( SCIPreallocBufferArray(scip, scalars, requiredsize) ); /* call function a second time with enough memory */ - SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, requiredsize, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, requiredsize, constant, &requiredsize) ); assert(requiredsize <= *nvars); } diff --git a/src/scip/prop_genvbounds.c b/src/scip/prop_genvbounds.c index db3dc7ed4a..d521a055fe 100644 --- a/src/scip/prop_genvbounds.c +++ b/src/scip/prop_genvbounds.c @@ -2480,7 +2480,7 @@ SCIP_DECL_PROPEXITPRE(propExitpreGenvbounds) /* replace non-active by active variables and update constant; note that this may result in coefficients where * SCIPisZero() is true; this should not create any problems */ - SCIP_CALL( SCIPgetProbvarLinearSum(scip, genvbound->vars, genvbound->coefs, &genvbound->ncoefs, genvbound->ncoefs, &genvbound->constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, genvbound->vars, genvbound->coefs, &genvbound->ncoefs, genvbound->ncoefs, &genvbound->constant, &requiredsize) ); /* if space was not enough we need to resize the buffers */ if( requiredsize > genvbound->ncoefs ) @@ -2493,7 +2493,7 @@ SCIP_DECL_PROPEXITPRE(propExitpreGenvbounds) genvbound->coefssize = requiredsize; } - SCIP_CALL( SCIPgetProbvarLinearSum(scip, genvbound->vars, genvbound->coefs, &genvbound->ncoefs, requiredsize, &genvbound->constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, genvbound->vars, genvbound->coefs, &genvbound->ncoefs, requiredsize, &genvbound->constant, &requiredsize) ); assert(requiredsize <= genvbound->ncoefs); } diff --git a/src/scip/reader_ccg.c b/src/scip/reader_ccg.c index ab80ab4f9f..aa7c5813bd 100644 --- a/src/scip/reader_ccg.c +++ b/src/scip/reader_ccg.c @@ -184,14 +184,14 @@ SCIP_RETCODE getActiveVariables( if( transformed ) { - SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize) ); if( requiredsize > *nvars ) { SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &scalars, requiredsize) ); - SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize) ); assert( requiredsize <= *nvars ); } } diff --git a/src/scip/reader_fzn.c b/src/scip/reader_fzn.c index f8af1e533c..ffd83fbb80 100644 --- a/src/scip/reader_fzn.c +++ b/src/scip/reader_fzn.c @@ -3883,14 +3883,14 @@ SCIP_RETCODE getActiveVariables( if( transformed ) { - SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *nvars, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *nvars, constant, &requiredsize) ); if( requiredsize > *nvars ) { SCIP_CALL( SCIPreallocBufferArray(scip, vars, requiredsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, scalars, requiredsize) ); - SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, requiredsize, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, requiredsize, constant, &requiredsize) ); assert( requiredsize <= *nvars ); } } diff --git a/src/scip/reader_gms.c b/src/scip/reader_gms.c index c9b56a56eb..72f358505e 100644 --- a/src/scip/reader_gms.c +++ b/src/scip/reader_gms.c @@ -107,7 +107,7 @@ SCIP_RETCODE getActiveVariables( if( transformed ) { - SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *varssize, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *varssize, constant, &requiredsize) ); if( requiredsize > *varssize ) { @@ -115,7 +115,7 @@ SCIP_RETCODE getActiveVariables( SCIP_CALL( SCIPreallocBufferArray(scip, vars, *varssize) ); SCIP_CALL( SCIPreallocBufferArray(scip, scalars, *varssize) ); - SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *varssize, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *varssize, constant, &requiredsize) ); assert(requiredsize <= *varssize); } } diff --git a/src/scip/reader_lp.c b/src/scip/reader_lp.c index 6f7ec1958a..ec3885abbc 100644 --- a/src/scip/reader_lp.c +++ b/src/scip/reader_lp.c @@ -2537,14 +2537,14 @@ SCIP_RETCODE getActiveVariables( if( transformed ) { - SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *nvars, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *nvars, constant, &requiredsize) ); if( requiredsize > *nvars ) { SCIP_CALL( SCIPreallocBufferArray(scip, vars, requiredsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, scalars, requiredsize) ); - SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, requiredsize, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, requiredsize, constant, &requiredsize) ); assert( requiredsize <= *nvars ); } } diff --git a/src/scip/reader_mps.c b/src/scip/reader_mps.c index 0c0b1114a0..08d50af467 100644 --- a/src/scip/reader_mps.c +++ b/src/scip/reader_mps.c @@ -2961,14 +2961,14 @@ SCIP_RETCODE getLinearCoeffs( /* retransform given variables to active variables */ if( transformed ) { - SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activevals, &nactivevars, nactivevars, &activeconstant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activevals, &nactivevars, nactivevars, &activeconstant, &requiredsize) ); if( requiredsize > nactivevars ) { SCIP_CALL( SCIPreallocBufferArray(scip, &activevars, requiredsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &activevals, requiredsize) ); - SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activevals, &nactivevars, requiredsize, &activeconstant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activevals, &nactivevars, requiredsize, &activeconstant, &requiredsize) ); assert( requiredsize <= nactivevars ); } } diff --git a/src/scip/reader_opb.c b/src/scip/reader_opb.c index 56241e13ec..cef946c61b 100644 --- a/src/scip/reader_opb.c +++ b/src/scip/reader_opb.c @@ -1787,14 +1787,14 @@ SCIP_RETCODE getActiveVariables( if( transformed ) { - SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize) ); if( requiredsize > *nvars ) { SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &scalars, requiredsize) ); - SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize) ); assert( requiredsize <= *nvars ); } } diff --git a/src/scip/reader_pbm.c b/src/scip/reader_pbm.c index ca58607378..2aa0d3b8cb 100644 --- a/src/scip/reader_pbm.c +++ b/src/scip/reader_pbm.c @@ -96,14 +96,14 @@ SCIP_RETCODE getActiveVariables( if( transformed ) { - SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize) ); if( requiredsize > *nvars ) { SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &scalars, requiredsize) ); - SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize) ); assert(requiredsize <= *nvars); } } diff --git a/src/scip/reader_pip.c b/src/scip/reader_pip.c index 409c59ba13..eea02e5c93 100644 --- a/src/scip/reader_pip.c +++ b/src/scip/reader_pip.c @@ -1758,14 +1758,14 @@ SCIP_RETCODE getActiveVariables( if( transformed ) { - SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *nvars, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *nvars, constant, &requiredsize) ); if( requiredsize > *nvars ) { SCIP_CALL( SCIPreallocBufferArray(scip, vars, requiredsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, scalars, requiredsize) ); - SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, requiredsize, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, requiredsize, constant, &requiredsize) ); assert( requiredsize <= *nvars ); } } diff --git a/src/scip/reader_ppm.c b/src/scip/reader_ppm.c index 22d5f2f0d0..f0890a5008 100644 --- a/src/scip/reader_ppm.c +++ b/src/scip/reader_ppm.c @@ -115,14 +115,14 @@ SCIP_RETCODE getActiveVariables( if( transformed ) { - SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, *nvars, constant, &requiredsize) ); if( requiredsize > *nvars ) { SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &scalars, requiredsize) ); - SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, nvars, requiredsize, constant, &requiredsize) ); assert( requiredsize <= *nvars ); } } diff --git a/src/scip/scip_var.c b/src/scip/scip_var.c index b7d29fb29d..264a7408d7 100644 --- a/src/scip/scip_var.c +++ b/src/scip/scip_var.c @@ -1708,11 +1708,12 @@ SCIP_RETCODE SCIPflattenVarAggregationGraph( * active variables, that is b_1*y_1 + ... + b_m*y_m + d. * * If the number of needed active variables is greater than the available slots in the variable array, nothing happens - * except that the required size is stored in the corresponding variable (requiredsize). Otherwise, the active variable - * representation is stored in the variable array, scalar array and constant. + * except that an upper bound on the required size is stored in the variable requiredsize; otherwise, the active + * variable representation is stored in the arrays. * * The reason for this approach is that we cannot reallocate memory, since we do not know how the memory has been - * allocated (e.g., by a C++ 'new' or SCIP functions). + * allocated (e.g., by a C++ 'new' or SCIP functions). Note that requiredsize is an upper bound due to possible + * cancelations. * * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. @@ -1751,9 +1752,8 @@ SCIP_RETCODE SCIPgetProbvarLinearSum( SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c which * will chnage to constant d in the linear sum b_1*y_1 + ... + b_m*y_m + * d w.r.t. the active variables */ - int* requiredsize, /**< pointer to store the required array size for the linear sum w.r.t. the - * active variables */ - SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */ + int* requiredsize /**< pointer to store an upper bound on the required size for the linear sum + * w.r.t. the active variables */ ) { assert( scip != NULL ); @@ -1765,7 +1765,7 @@ SCIP_RETCODE SCIPgetProbvarLinearSum( assert( *nvars <= varssize ); SCIP_CALL( SCIPcheckStage(scip, "SCIPgetProbvarLinearSum", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); - SCIP_CALL( SCIPvarGetActiveRepresentatives(scip->set, vars, scalars, nvars, varssize, constant, requiredsize, mergemultiples) ); + SCIP_CALL( SCIPvarGetActiveRepresentatives(scip->set, vars, scalars, nvars, varssize, constant, requiredsize) ); return SCIP_OKAY; } diff --git a/src/scip/scip_var.h b/src/scip/scip_var.h index e46ee580d1..ccf0d88ff8 100644 --- a/src/scip/scip_var.h +++ b/src/scip/scip_var.h @@ -769,11 +769,12 @@ SCIP_RETCODE SCIPflattenVarAggregationGraph( * active variables, that is b_1*y_1 + ... + b_m*y_m + d. * * If the number of needed active variables is greater than the available slots in the variable array, nothing happens - * except that the required size is stored in the corresponding variable (requiredsize). Otherwise, the active variable - * representation is stored in the variable array, scalar array and constant. + * except that an upper bound on the required size is stored in the variable requiredsize; otherwise, the active + * variable representation is stored in the arrays. * * The reason for this approach is that we cannot reallocate memory, since we do not know how the memory has been - * allocated (e.g., by a C++ 'new' or SCIP functions). + * allocated (e.g., by a C++ 'new' or SCIP functions). Note that requiredsize is an upper bound due to possible + * cancelations. * * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. @@ -813,9 +814,8 @@ SCIP_RETCODE SCIPgetProbvarLinearSum( SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c which * will chnage to constant d in the linear sum b_1*y_1 + ... + b_m*y_m + * d w.r.t. the active variables */ - int* requiredsize, /**< pointer to store the required array size for the linear sum w.r.t. the - * active variables */ - SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */ + int* requiredsize /**< pointer to store an upper bound on the required size for the linear sum + * w.r.t. the active variables */ ); /** transforms given variable, scalar and constant to the corresponding active, fixed, or diff --git a/src/scip/sol.c b/src/scip/sol.c index 9a42754d6c..799220b962 100644 --- a/src/scip/sol.c +++ b/src/scip/sol.c @@ -2126,7 +2126,7 @@ SCIP_RETCODE SCIPsolRetransform( /* get active representation of the original variable */ SCIP_CALL( SCIPvarGetActiveRepresentatives(set, activevars, activevals, &nactivevars, ntransvars + 1, &constant, - &requiredsize, TRUE) ); + &requiredsize) ); assert(requiredsize <= ntransvars); /* compute solution value of the original variable */ diff --git a/src/scip/symmetry_graph.c b/src/scip/symmetry_graph.c index 2a4fb62c1e..16603bb368 100644 --- a/src/scip/symmetry_graph.c +++ b/src/scip/symmetry_graph.c @@ -1856,14 +1856,14 @@ SCIP_RETCODE SCIPgetSymActiveVariables( if( transformed ) { - SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *nvars, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, *nvars, constant, &requiredsize) ); if( requiredsize > *nvars ) { SCIP_CALL( SCIPreallocBufferArray(scip, vars, requiredsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, scalars, requiredsize) ); - SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, requiredsize, constant, &requiredsize, TRUE) ); + SCIP_CALL( SCIPgetProbvarLinearSum(scip, *vars, *scalars, nvars, requiredsize, constant, &requiredsize) ); assert(requiredsize <= *nvars); } } diff --git a/src/scip/var.c b/src/scip/var.c index 66bf95ff7e..72258c65ca 100644 --- a/src/scip/var.c +++ b/src/scip/var.c @@ -61,6 +61,7 @@ #include "scip/pub_prop.h" #include "scip/pub_var.h" #include "scip/relax.h" +#include "scip/scip_prob.h" #include "scip/set.h" #include "scip/sol.h" #include "scip/stat.h" @@ -3927,12 +3928,13 @@ SCIP_RETCODE SCIPvarFix( /** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant * - * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except - * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the - * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays. + * If the number of needed active variables is greater than the available slots in the variable array, nothing happens + * except that an upper bound on the required size is stored in the variable requiredsize; otherwise, the active + * variable representation is stored in the arrays. * - * The reason for this approach is that we cannot reallocate memory, since we do not know how the - * memory has been allocated (e.g., by a C++ 'new' or SCIP functions). + * The reason for this approach is that we cannot reallocate memory, since we do not know how the memory has been + * allocated (e.g., by a C++ 'new' or SCIP functions). Note that requiredsize is an upper bound due to possible + * cancelations. */ SCIP_RETCODE SCIPvarGetActiveRepresentatives( SCIP_SET* set, /**< global SCIP settings */ @@ -3941,21 +3943,18 @@ SCIP_RETCODE SCIPvarGetActiveRepresentatives( int* nvars, /**< pointer to number of variables and values in vars and scalars array */ int varssize, /**< available slots in vars and scalars array */ SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */ - int* requiredsize, /**< pointer to store the required array size for the active variables */ - SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */ + int* requiredsize /**< pointer to store an uppper bound on the required size for the active variables */ ) { SCIP_VAR** activevars; - SCIP_Real* activescalars; - int nactivevars; SCIP_Real activeconstant; SCIP_Bool activeconstantinf; int activevarssize; + int nactivevars; SCIP_VAR* var; SCIP_Real scalar; int v; - int k; SCIP_VAR** tmpvars; SCIP_VAR** multvars; @@ -3968,20 +3967,11 @@ SCIP_RETCODE SCIPvarGetActiveRepresentatives( SCIP_VAR* multvar; SCIP_Real multscalar; SCIP_Real multconstant; - int pos; - - int noldtmpvars; - - SCIP_VAR** tmpvars2; - SCIP_Real* tmpscalars2; - int tmpvarssize2; - int ntmpvars2; - - SCIP_Bool sortagain = FALSE; + SCIP_VARSTATUS varstatus; + int ntotalvars; assert(set != NULL); assert(nvars != NULL); - assert(scalars != NULL || *nvars == 0); assert(constant != NULL); assert(requiredsize != NULL); assert(*nvars <= varssize); @@ -3992,6 +3982,7 @@ SCIP_RETCODE SCIPvarGetActiveRepresentatives( return SCIP_OKAY; assert(vars != NULL); + assert(scalars != NULL); /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */ if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) ) @@ -4001,291 +3992,99 @@ SCIP_RETCODE SCIPvarGetActiveRepresentatives( return SCIP_OKAY; } - nactivevars = 0; - activeconstant = 0.0; - activeconstantinf = FALSE; - activevarssize = (*nvars) * 2; - ntmpvars = *nvars; + /* allocate temporary list of variables */ tmpvarssize = *nvars; + SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars, tmpvarssize) ); - tmpvarssize2 = 1; - - /* allocate temporary memory */ - SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) ); - SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) ); + /* allocate memory for list of active variables */ + activevarssize = MAX(10, 2 * (*nvars)); /* take the maximum to avoid small reallocations */ SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) ); - SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) ); - SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) ); - SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) ); - /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables - * first, first get all corresponding variables with status loose, column, multaggr or fixed - */ - for( v = ntmpvars - 1; v >= 0; --v ) - { - var = tmpvars[v]; - scalar = tmpscalars[v]; + /* allocate dense array for storing scalars (to avoid checking for duplicate variables) */ + ntotalvars = SCIPgetNTotalVars(set->scip); + SCIP_CALL( SCIPsetAllocCleanBufferArray(set, &tmpscalars, ntotalvars) ); + /* perform one round of replacing variables by their active, fixed or multi-aggregated counterparts */ + activeconstant = 0.0; + nactivevars = 0; + ntmpvars = 0; + for( v = 0; v < *nvars; ++v ) + { + var = vars[v]; assert(var != NULL); - /* transforms given variable, scalar and constant to the corresponding active, fixed, or - * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed - * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant". - */ + scalar = scalars[v]; + + /* Transforms variable, scalar and constant to corresponding active, fixed, or multi-aggregated variable, scalar + * and constant; activeconstant collects the sum of all constants (even for variables with scalar == 0.0). */ SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) ); assert(var != NULL); assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/ assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/ - activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant); + varstatus = SCIPvarGetStatus(var); + assert( varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN + || varstatus == SCIP_VARSTATUS_MULTAGGR || varstatus == SCIP_VARSTATUS_FIXED); - assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE - || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN - || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR - || SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED); - - tmpvars[v] = var; - tmpscalars[v] = scalar; - } - noldtmpvars = ntmpvars; - - /* sort all variables to combine equal variables easily */ - SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, noldtmpvars); - ntmpvars = 0; - for( v = 1; v < noldtmpvars; ++v ) - { - /* combine same variables */ - if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 ) + /* enter nonzero scalars into dense array and list */ + if( scalar != 0.0 ) { - tmpscalars[ntmpvars] += tmpscalars[v]; - } - else - { - ++ntmpvars; - if( v > ntmpvars ) + assert(0 <= var->index && var->index < ntotalvars); + if( tmpscalars[var->index] == 0.0 ) { - tmpscalars[ntmpvars] = tmpscalars[v]; - tmpvars[ntmpvars] = tmpvars[v]; + if( varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN ) + activevars[nactivevars++] = var; /* store active variables */ + else if( varstatus == SCIP_VARSTATUS_MULTAGGR ) + tmpvars[ntmpvars++] = var; /* enter mutli-aggregated variables in list to be processed below */ } + tmpscalars[var->index] += scalar; } } - ++ntmpvars; + assert(ntmpvars <= *nvars); + assert(nactivevars <= *nvars); -#ifdef SCIP_MORE_DEBUG - for( v = 1; v < ntmpvars; ++v ) - assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0); -#endif + /* store whether the constant is infinite */ + activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant); /* collect for each variable the representation in active variables */ while( ntmpvars >= 1 ) { --ntmpvars; - ntmpvars2 = 0; - var = tmpvars[ntmpvars]; - scalar = tmpscalars[ntmpvars]; + var = tmpvars[ntmpvars]; assert(var != NULL); + assert(0 <= var->index && var->index < ntotalvars); + assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR); - /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */ + scalar = tmpscalars[var->index]; + /* the scalar can be 0 if the variable has been treated before and is zeroed below */ if( scalar == 0.0 ) continue; - assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE - || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN - || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR - || SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED); + /* x = a_1*y_1 + ... + a_n*y_n + c */ + nmultvars = var->data.multaggr.nvars; + multvars = var->data.multaggr.vars; + multscalars = var->data.multaggr.scalars; - switch( SCIPvarGetStatus(var) ) - { - case SCIP_VARSTATUS_LOOSE: - case SCIP_VARSTATUS_COLUMN: - /* x = a*y + c */ - if( nactivevars >= activevarssize ) - { - activevarssize *= 2; - SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) ); - SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) ); - assert(nactivevars < activevarssize); - } - activevars[nactivevars] = var; - activescalars[nactivevars] = scalar; - nactivevars++; - break; - - case SCIP_VARSTATUS_MULTAGGR: - /* x = a_1*y_1 + ... + a_n*y_n + c */ - nmultvars = var->data.multaggr.nvars; - multvars = var->data.multaggr.vars; - multscalars = var->data.multaggr.scalars; - sortagain = TRUE; - - if( nmultvars + ntmpvars > tmpvarssize ) - { - while( nmultvars + ntmpvars > tmpvarssize ) - tmpvarssize *= 2; - SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) ); - SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) ); - assert(nmultvars + ntmpvars <= tmpvarssize); - } - - if( nmultvars > tmpvarssize2 ) - { - while( nmultvars > tmpvarssize2 ) - tmpvarssize2 *= 2; - SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) ); - SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) ); - assert(nmultvars <= tmpvarssize2); - } - - --nmultvars; - - for( ; nmultvars >= 0; --nmultvars ) - { - multvar = multvars[nmultvars]; - multscalar = multscalars[nmultvars]; - multconstant = 0; - - assert(multvar != NULL); - SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) ); - assert(multvar != NULL); - - assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE - || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN - || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR - || SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED); - - if( !activeconstantinf ) - { - assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar)); - - if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) ) - { - assert(scalar != 0.0); - if( scalar * multconstant > 0.0 ) - { - activeconstant = SCIPsetInfinity(set); - activeconstantinf = TRUE; - } - else - { - activeconstant = -SCIPsetInfinity(set); - activeconstantinf = TRUE; - } - } - else - activeconstant += scalar * multconstant; - } -#ifndef NDEBUG - else - { - assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 && - (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant)))); - assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 && - (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant)))); - } -#endif - - if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) ) - { - assert(SCIPvarCompare(tmpvars[pos], multvar) == 0); - tmpscalars[pos] += scalar * multscalar; - } - else - { - tmpvars2[ntmpvars2] = multvar; - tmpscalars2[ntmpvars2] = scalar * multscalar; - ++(ntmpvars2); - assert(ntmpvars2 <= tmpvarssize2); - } - } + /* mark variable as treated */ + tmpscalars[var->index] = 0.0; - if( ntmpvars2 > 0 ) - { - /* sort all variables to combine equal variables easily */ - SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2); - pos = 0; - for( v = 1; v < ntmpvars2; ++v ) - { - /* combine same variables */ - if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 ) - { - tmpscalars2[pos] += tmpscalars2[v]; - } - else - { - ++pos; - if( v > pos ) - { - tmpscalars2[pos] = tmpscalars2[v]; - tmpvars2[pos] = tmpvars2[v]; - } - } - } - ntmpvars2 = pos + 1; -#ifdef SCIP_MORE_DEBUG - for( v = 1; v < ntmpvars2; ++v ) - { - assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0); - } - for( v = 1; v < ntmpvars; ++v ) - { - assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0); - } -#endif - v = ntmpvars - 1; - k = ntmpvars2 - 1; - pos = ntmpvars + ntmpvars2 - 1; - ntmpvars += ntmpvars2; + /* loop through variables of multi-aggregation */ + for( v = 0; v < nmultvars; ++v ) + { + multvar = multvars[v]; + multscalar = multscalars[v]; + multconstant = 0.0; - while( v >= 0 && k >= 0 ) - { - assert(pos >= 0); - assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0); - if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 ) - { - tmpvars[pos] = tmpvars[v]; - tmpscalars[pos] = tmpscalars[v]; - --v; - } - else - { - tmpvars[pos] = tmpvars2[k]; - tmpscalars[pos] = tmpscalars2[k]; - --k; - } - --pos; - assert(pos >= 0); - } - while( v >= 0 ) - { - assert(pos >= 0); - tmpvars[pos] = tmpvars[v]; - tmpscalars[pos] = tmpscalars[v]; - --v; - --pos; - } - while( k >= 0 ) - { - assert(pos >= 0); - tmpvars[pos] = tmpvars2[k]; - tmpscalars[pos] = tmpscalars2[k]; - --k; - --pos; - } - } -#ifdef SCIP_MORE_DEBUG - for( v = 1; v < ntmpvars; ++v ) - { - assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0); - } -#endif + assert(multvar != NULL); + SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) ); + assert(multvar != NULL); + /* handle constant */ if( !activeconstantinf ) { assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar)); - multconstant = SCIPvarGetMultaggrConstant(var); - if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) ) { assert(scalar != 0.0); @@ -4306,97 +4105,103 @@ SCIP_RETCODE SCIPvarGetActiveRepresentatives( #ifndef NDEBUG else { - multconstant = SCIPvarGetMultaggrConstant(var); assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 && (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant)))); assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 && (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant)))); } #endif - break; - case SCIP_VARSTATUS_FIXED: - case SCIP_VARSTATUS_ORIGINAL: - case SCIP_VARSTATUS_AGGREGATED: - case SCIP_VARSTATUS_NEGATED: - default: - /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for - * fixed variables and is handled already - */ - assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED); - assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub)); - } - } - - if( mergemultiples ) - { - if( sortagain ) - { - /* sort variable and scalar array by variable index */ - SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars); + /* Note that the variable can have a nonzero constant but 0 scalar. */ + if( multscalar == 0.0 ) + continue; - /* eliminate duplicates and count required size */ - v = nactivevars - 1; - while( v > 0 ) + /* enter variable into list if not already present */ + assert(0 <= multvar->index && multvar->index < ntotalvars); + if( tmpscalars[multvar->index] == 0.0 ) { - /* combine both variable since they are the same */ - if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 ) + varstatus = SCIPvarGetStatus(multvar); + if( varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN ) { - if( activescalars[v - 1] + activescalars[v] != 0.0 ) + /* store active variables */ + if( nactivevars >= activevarssize ) { - activescalars[v - 1] += activescalars[v]; - --nactivevars; - activevars[v] = activevars[nactivevars]; - activescalars[v] = activescalars[nactivevars]; + activevarssize *= 2; + SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) ); + assert(nactivevars < activevarssize); } - else + activevars[nactivevars++] = multvar; + } + else if( varstatus == SCIP_VARSTATUS_MULTAGGR ) + { + /* ensure storage */ + if( ntmpvars >= tmpvarssize ) { - --nactivevars; - activevars[v] = activevars[nactivevars]; - activescalars[v] = activescalars[nactivevars]; - --nactivevars; - --v; - activevars[v] = activevars[nactivevars]; - activescalars[v] = activescalars[nactivevars]; + tmpvarssize *= 2; + SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) ); + assert(ntmpvars <= tmpvarssize); } + tmpvars[ntmpvars++] = multvar; } - --v; } + + /* transfer new scalar to dense array in any case */ + tmpscalars[multvar->index] += scalar * multscalar; + assert(scalar * multscalar != 0.0); } - /* the variables were added in reverse order, we revert the order now; - * this should not be necessary, but not doing this changes the behavior sometimes - */ - else + + /* handle constant of multi-aggregation */ + if( !activeconstantinf ) { - SCIP_VAR* tmpvar; - SCIP_Real tmpscalar; + assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar)); - for( v = 0; v < nactivevars / 2; ++v ) + multconstant = SCIPvarGetMultaggrConstant(var); + + if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) ) { - tmpvar = activevars[v]; - tmpscalar = activescalars[v]; - activevars[v] = activevars[nactivevars - 1 - v]; - activescalars[v] = activescalars[nactivevars - 1 - v]; - activevars[nactivevars - 1 - v] = tmpvar; - activescalars[nactivevars - 1 - v] = tmpscalar; + assert(scalar != 0.0); + if( scalar * multconstant > 0.0 ) + { + activeconstant = SCIPsetInfinity(set); + activeconstantinf = TRUE; + } + else + { + activeconstant = -SCIPsetInfinity(set); + activeconstantinf = TRUE; + } } + else + activeconstant += scalar * multconstant; + } +#ifndef NDEBUG + else + { + multconstant = SCIPvarGetMultaggrConstant(var); + assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 && + (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant)))); + assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 && + (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant)))); } +#endif } - *requiredsize = nactivevars; + /* Here, nactivevars is an upper bound on the required size, because of possible cancellation. We could compute the + * actual size, but this would need another loop through the active variables. We therefore take the upper bound. */ + + /* return results */ + *requiredsize = nactivevars; if( varssize >= *requiredsize ) { assert(vars != NULL); - *nvars = *requiredsize; - if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) ) { - /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */ + /* if activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */ if( activeconstantinf ) - (*constant) = activeconstant; + *constant = activeconstant; else - (*constant) += activeconstant; + *constant += activeconstant; } #ifndef NDEBUG else @@ -4407,22 +4212,44 @@ SCIP_RETCODE SCIPvarGetActiveRepresentatives( #endif /* copy active variable and scalar array to the given arrays */ - for( v = 0; v < *nvars; ++v ) + *nvars = 0; + for( v = 0; v < nactivevars; ++v ) + { + var = activevars[v]; + + assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN); + assert(0 <= var->index && var->index < ntotalvars); + + /* due to cancelation, the scalar could become 0 */ + if( tmpscalars[var->index] != 0.0 ) + { + vars[*nvars] = var; + scalars[*nvars] = tmpscalars[var->index]; + assert(scalars[*nvars] != 0.0); + ++(*nvars); + } + + /* clean buffer again */ + tmpscalars[var->index] = 0.0; + } + } + else + { + /* clean buffer again */ + for( v = 0; v < nactivevars; ++v ) { - vars[v] = activevars[v]; - scalars[v] = activescalars[v]; /*lint !e613*/ + var = activevars[v]; + assert( 0 <= var->index && var->index < ntotalvars ); + tmpscalars[var->index] = 0.0; } } assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/ assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/ - SCIPsetFreeBufferArray(set, &tmpscalars); - SCIPsetFreeBufferArray(set, &tmpvars); - SCIPsetFreeBufferArray(set, &activescalars); + SCIPsetFreeCleanBufferArray(set, &tmpscalars); SCIPsetFreeBufferArray(set, &activevars); - SCIPsetFreeBufferArray(set, &tmpscalars2); - SCIPsetFreeBufferArray(set, &tmpvars2); + SCIPsetFreeBufferArray(set, &tmpvars); return SCIP_OKAY; } @@ -4480,16 +4307,17 @@ SCIP_RETCODE SCIPvarFlattenAggregationGraph( nmultvars = var->data.multaggr.nvars; multvarssize = var->data.multaggr.varssize; - SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) ); + SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize) ); if( multrequiredsize > multvarssize ) { SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) ); SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) ); multvarssize = multrequiredsize; - SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) ); + SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize) ); assert( multrequiredsize <= multvarssize ); } + /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?). * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one * may loose performance hereby, since aggregated variables are easier to handle. @@ -5527,13 +5355,13 @@ SCIP_RETCODE SCIPvarMultiaggregate( SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) ); /* get all active variables for multi-aggregation */ - SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) ); + SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize) ); if( tmprequiredsize > tmpvarssize ) { SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) ); SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) ); tmpvarssize = tmprequiredsize; - SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) ); + SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize) ); assert( tmprequiredsize <= tmpvarssize ); } diff --git a/src/scip/var.h b/src/scip/var.h index eae4a16a9d..5d96790316 100644 --- a/src/scip/var.h +++ b/src/scip/var.h @@ -403,12 +403,13 @@ SCIP_RETCODE SCIPvarFix( /** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant * - * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except - * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the - * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays. + * If the number of needed active variables is greater than the available slots in the variable array, nothing happens + * except that an upper bound on the required size is stored in the variable requiredsize; otherwise, the active + * variable representation is stored in the arrays. * - * The reason for this approach is that we cannot reallocate memory, since we do not know how the - * memory has been allocated (e.g., by a C++ 'new' or SCIP functions). + * The reason for this approach is that we cannot reallocate memory, since we do not know how the memory has been + * allocated (e.g., by a C++ 'new' or SCIP functions). Note that requiredsize is an upper bound due to possible + * cancelations. */ SCIP_RETCODE SCIPvarGetActiveRepresentatives( SCIP_SET* set, /**< global SCIP settings */ @@ -417,8 +418,7 @@ SCIP_RETCODE SCIPvarGetActiveRepresentatives( int* nvars, /**< pointer to number of variables and values in vars and vals array */ int varssize, /**< available slots in vars and scalars array */ SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */ - int* requiredsize, /**< pointer to store the required array size for the active variables */ - SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */ + int* requiredsize /**< pointer to store an uppper bound on the required size for the active variables */ ); /** transforms given variable, scalar and constant to the corresponding active, fixed, or