|
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sepa_mcf.c
Go to the documentation of this file.
28 * (1) sum_{a in delta^+(v)} f_a^k - sum_{a in delta^-(v)} f_a^k <= -d_v^k for all v in V and k in K
31 * Constraints (1) are flow conservation constraints, which say that for each commodity k and node v the
32 * outflow (delta^+(v)) minus the inflow (delta^-(v)) of a node v must not exceed the negative of the demand of
33 * node v in commodity k. To say it the other way around, inflow minus outflow must be at least equal to the demand.
34 * Constraints (2) are the arc capacity constraints, which say that the sum of all flow over an arc a must not
36 * c_a x_a does not need to be a single product of a capacity and an integer variable; we also accept general scalar
40 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
63 #define SEPA_DELAY FALSE /**< should separation method be delayed, if other separators found cuts? */
67 #define DEFAULT_MAXWEIGHTRANGE 1e+06 /**< maximal valid range max(|weights|)/min(|weights|) of row weights for CMIR */
68 #define DEFAULT_MAXTESTDELTA 20 /**< maximal number of different deltas to try (-1: unlimited) for CMIR */
69 #define DEFAULT_TRYNEGSCALING FALSE /**< should negative values also be tested in scaling? for CMIR */
70 #define DEFAULT_FIXINTEGRALRHS TRUE /**< should an additional variable be complemented if f0 = 0? for CMIR */
71 #define DEFAULT_DYNAMICCUTS TRUE /**< should generated cuts be removed from the LP if they are no longer tight? */
73 #define DEFAULT_MAXSEPACUTS 100 /**< maximal number of cuts separated per separation round (-1: unlimited) */
74 #define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of cuts separated per separation round in root node (-1: unlimited) */
75 #define DEFAULT_MAXINCONSISTENCYRATIO 0.02 /**< maximum inconsistency ratio (inconsistencies/(arcs*commodities)) at all */
76 #define DEFAULT_MAXARCINCONSISTENCYRATIO 0.5 /**< maximum inconsistency ratio for arcs not to be deleted */
77 #define DEFAULT_CHECKCUTSHORECONNECTIVITY TRUE /**< should we only separate if the cuts shores are connected */
78 #define DEFAULT_SEPARATESINGLENODECUTS TRUE /**< should we separate inequalities based on single node cuts */
93 #define MAXFLOWVARFLOWROWRATIO 100.0 /**< maximum ratio flowvars/flowrows for the separator to be switched on */
94 #define MAXARCNODERATIO 100.0 /**< maximum ratio arcs/nodes for the separator to be switched on */
97 #define MINCOMNODESFRACTION 0.5 /**< minimal size of commodity relative to largest commodity to keep it in the network */
100 #define MAXCAPACITYSLACK 0.1 /**< maximal slack of weighted capacity constraints to use in aggregation */
101 #define UNCAPACITATEDARCSTRESHOLD 0.8 /**< threshold for the percentage of commodities an uncapacitated arc should appear in */
104 /* #define OUTPUTGRAPH should a .gml graph of the network be generated for debugging purposes? */
130 SCIP_MCFMODELTYPE_UNDIRECTED = 2 /**< directed network where anti-parallel arcs share the capacity */
148 SCIP_Real** nodeflowscales; /**< scaling factors to convert nodeflowrows[v][k] into a +/-1 <= row */
149 SCIP_Bool** nodeflowinverted; /**< does nodeflowrows[v][k] have to be inverted to fit the network structure? */
170 int nclusters; /**< number of clusters to generate in the shrunken network -- default separation */
171 SCIP_Real maxweightrange; /**< maximal valid range max(|weights|)/min(|weights|) of row weights */
172 int maxtestdelta; /**< maximal number of different deltas to try (-1: unlimited) -- default separation */
175 SCIP_Bool dynamiccuts; /**< should generated cuts be removed from the LP if they are no longer tight? */
178 int maxsepacutsroot; /**< maximal number of cmir cuts separated per separation round in root node -- default separation */
179 SCIP_Real maxinconsistencyratio; /**< maximum inconsistency ratio (inconsistencies/(arcs*commodities)) for separation at all*/
180 SCIP_Real maxarcinconsistencyratio; /**< maximum inconsistency ratio for arcs not to be deleted */
181 SCIP_Bool checkcutshoreconnectivity;/**< should we only separate if the cuts shores are connected */
182 SCIP_Bool separatesinglenodecuts; /**< should we separate inequalities based on single node cuts ? */
183 SCIP_Bool separateflowcutset; /**< should we separate flowcutset inequalities on the network cuts ? */
184 SCIP_Bool separateknapsack; /**< should we separate knapsack cover inequalities on the network cuts ? */
192 unsigned char* flowrowsigns; /**< potential or actual sides of rows to be used as flow conservation constraint */
194 SCIP_Real* flowrowscores; /**< score value indicating how sure we are that this is indeed a flow conservation constraint */
195 unsigned char* capacityrowsigns; /**< potential or actual sides of rows to be used as capacity constraint */
196 SCIP_Real* capacityrowscores; /**< score value indicating how sure we are that this is indeed a capacity constraint */
197 int* flowcands; /**< list of row indices that are candidates for flow conservation constraints */
204 int nemptycommodities; /**< number of commodities that have been discarded but still counted in 'ncommodities' */
221 int* newcols; /**< columns of current commodity that have to be inspected for incident flow conservation rows */
465 SCIP_CALL( SCIPallocMemoryArray(scip, &mcfnetwork->nodeflowrows[v], mcfnetwork->ncommodities) ); /*lint !e866*/
466 SCIP_CALL( SCIPallocMemoryArray(scip, &mcfnetwork->nodeflowscales[v], mcfnetwork->ncommodities) ); /*lint !e866*/
467 SCIP_CALL( SCIPallocMemoryArray(scip, &mcfnetwork->nodeflowinverted[v], mcfnetwork->ncommodities) ); /*lint !e866*/
555 /* Scale constraint such that the coefficients for the flow variables are normalized in such a way that coefficients in
557 * This is needed for binary flow variable models in which the demand of each commodity is stored as the coefficient in
558 * the capacity constraints. Since it may happen (e.g., due to presolve) that different capacity constraints are scaled
559 * differently, we need to find scaling factors to make the demand coefficients of each commodity equal.
560 * To do this, we scale the first capacity constraint with +1 and then store the coefficients of the flow variables
561 * as target demands for the commodities. Then, we scale the other constraints in such a way that these demands are hit, if possible.
562 * Note that for continuous flow variable models, the coefficients in the capacity constraints are usually +1.0.
584 /* use negative scaling if we use the left hand side, use positive scaling if we use the right hand side */
610 assert(0 <= compnodeid[mcfdata->arcsources[globala]] && compnodeid[mcfdata->arcsources[globala]] < mcfnetwork->nnodes);
616 assert(0 <= compnodeid[mcfdata->arctargets[globala]] && compnodeid[mcfdata->arctargets[globala]] < mcfnetwork->nnodes);
681 MCFdebugMessage("arc %2d [%2d -> %2d]: ", a, mcfnetwork->arcsources[a], mcfnetwork->arctargets[a]);
684 MCFdebugMessage("<%s> [%+g]\n", SCIProwGetName(mcfnetwork->arccapacityrows[a]), mcfnetwork->arccapacityscales[a]);
732 MCFdebugMessage(" col <%s>: arc %d\n", SCIPvarGetName(SCIPcolGetVar(cols[c])), colarcid != NULL ? colarcid[c] : -1);
737 MCFdebugMessage(" row <%s>: node %d [sign:%+d, inv:%+d]\n", SCIProwGetName(rows[r]), rownodeid != NULL ? rownodeid[r] : -1,
790 MCFdebugMessage(" col <%s> [%g,%g]\n", SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var));
800 if( rowcommodity[r] == -1 && (capacityrowsigns == NULL || (capacityrowsigns[r] & (LHSASSIGNED | RHSASSIGNED)) == 0) )
994 /** @todo go through list of several model types, depending on the current model type throw away invalid constraints
1032 SCIPdebugMessage("%4d [score: %2g]: %s\n", mcfdata->flowcands[r], flowrowscores[mcfdata->flowcands[r]],
1084 /* identify model type and set the maximal number of flow variables per capacity constraint and commodity */
1088 maxcolspercommoditylimit = 2; /* will be set to 1 later if we detect that the network is directed */
1253 ABS((nposflowcoefs + nnegflowcoefs)/(SCIP_Real)ncoveredcommodities - maxcolspercommoditylimit);
1262 if( (capacityrowsigns[r] & RHSPOSSIBLE) != 0 && nnegflowcoefs == 0 && nposcapacitycoefs == 0 && nnegcapacitycoefs > 0 )
1264 if( (capacityrowsigns[r] & LHSPOSSIBLE) != 0 && nposflowcoefs == 0 && nposcapacitycoefs > 0 && nnegcapacitycoefs == 0 )
1272 * use slightly increased denominator in order to not increase score too much for very few commodities
1294 capacityrowscores[r] += 20.0 * MAX(nposflowcoefs, nnegflowcoefs)/MAX(1.0,(SCIP_Real)(nposflowcoefs + nnegflowcoefs));
1296 /* capacity coefficients are mostly of the same sign: score +10*max(npos,nneg)/(npos+nneg+1) */
1297 capacityrowscores[r] += 10.0 * MAX(nposcapacitycoefs, nnegcapacitycoefs)/(SCIP_Real)(nposcapacitycoefs+nnegcapacitycoefs+1.0);
1308 SCIPdebugMessage("row <%s>: maxcolspercommodity=%d capacityrowsign=%d nposflowcoefs=%d nnegflowcoefs=%d nposcapacitycoefs=%d nnegcapacitycoefs=%d nbadcoefs=%d nactivecommodities=%d sameflowcoef=%g -> score=%g\n",
1309 SCIProwGetName(row), maxcolspercommodity[r], capacityrowsigns[r], nposflowcoefs, nnegflowcoefs, nposcapacitycoefs, nnegcapacitycoefs, nbadcoefs, nactivecommodities, sameflowcoef, capacityrowscores[r]);
1314 /* if the model type should be detected automatically, count the number of directed and undirected capacity candidates */
1340 modeltype == SCIP_MCFMODELTYPE_DIRECTED ? "directed" : "undirected", directedcandsscore, undirectedcandsscore);
1389 SCIPsortInd(mcfdata->capacitycands, compCands, (void*)capacityrowscores, mcfdata->ncapacitycands);
1396 capacityrowscores[mcfdata->capacitycands[r]], SCIProwGetName(rows[mcfdata->capacitycands[r]]));
1420 SCIP_CALL( SCIPreallocMemoryArray(scip, &mcfdata->commoditysigns, mcfdata->commoditysignssize) );
1722 SCIPdebugMessage("deleting commodity %d (%d total commodities) with %d flow rows\n", k, ncommodities, nrows);
1780 /** checks whether the given row fits into the given commodity and returns the possible flow row signs */
1788 SCIP_Bool* invertcommodity /**< pointer to store whether the commodity has to be inverted to accommodate the row */
1907 SCIPdebugMessage(" -> discard flow row %d <%s>, comoditysign=%d\n", r, SCIProwGetName(row), commoditysigns[k]);
1919 SCIP_Bool* nextinvertcommodity /**< pointer to store whether current commodity has to be inverted to accommodate the next row */
1943 /* check if there are any columns left in the commodity that have not yet been inspected for incident flow rows */
1966 /* check whether column is incident to a valid flow row that fits into the current commodity */
2014 * Note: This is not the overall best row, only the one for the first column that has a valid row.
2099 * (iii) For the newly added columns search for an incident flow conservation constraint. Pick the one of highest ranking.
2125 SCIPdebugMessage(" -------------------start new commodity %d--------------------- \n", mcfdata->ncommodities );
2135 invertCommodity(scip, mcfdata, mcfdata->ncommodities-1, comrows, nnodes, comcolids, ncomcolids);
2152 SCIPdebugMessage(" -> finished commodity %d: identified %d nodes, maxnnodes=%d\n", mcfdata->ncommodities-1, nnodes, maxnnodes);
2154 /* if the commodity has too few nodes, or if it has much fewer nodes than the largest commodity, discard it */
2160 deleteCommodity(scip, mcfdata, mcfdata->ncommodities-1, comrows, nnodes, &ndelflowrows, &ndelflowvars);
2208 MCFdebugMessage("identified %d commodities (%d empty) with a maximum of %d nodes and %d flowrows, %d flowvars \n",
2223 /** Arc-Detection -- identifies capacity constraints for the arcs and assigns arc ids to columns and capacity constraints */
2334 SCIPdebugMessage("discarding capacity candidate row %d <%s> [score:%g]: %d assigned flowvars, %d unassigned flowvars\n",
2335 r, SCIProwGetName(capacityrow), mcfdata->capacityrowscores[r], nassignedflowvars, nunassignedflowvars);
2365 SCIPdebugMessage("assigning capacity row %d <%s> with sign %+d to arc %d [score:%g]: %d assigned flowvars, %d unassigned flowvars\n",
2366 r, SCIProwGetName(capacityrow), (capacityrowsigns[r] & RHSASSIGNED) != 0 ? +1 : -1, mcfdata->narcs,
2375 /* due to aggregations in preprocessing it may happen that a flow variable appears in multiple capacity constraints;
2389 /** collects all flow columns of all commodities (except the one of the base row) that are incident to the node described by the given flow row */
2455 assert(colarcid[caprowc] <= arcid); /* colarcid < arcid if column belongs to multiple arcs, for example, due to an aggregation in presolving */
2482 int basenposuncap, /**< number of uncapacitated vars in base node flow row with positive coeff*/
2483 int basenneguncap, /**< number of uncapacitated vars in base node flow row with negative coeff*/
2486 SCIP_Bool* invertcommodity /**< pointer to store whether the arcs in the commodity of the row have
2618 assert(modeltype == SCIP_MCFMODELTYPE_UNDIRECTED || rowcomsign * basearcpattern[arcid] * arcpattern[arcid] > 0);
2633 /* calculate the score: maximize overlap and use minimal number of non-overlapping entries as tie breaker */
2660 *score += 1.0 - (ABS(nneguncap - basenposuncap) + ABS(nposuncap - basenneguncap))/(2.0 * ncols + 1.0);
2662 *score += 1.0 - (ABS(nposuncap - basenposuncap) + ABS(nneguncap - basenneguncap))/(2.0 * ncols + 1.0);
2664 *score = MAX(*score, 1e-6); /* score may get negative due to many columns having the same arcid */
2668 SCIPdebugMessage(" -> node similarity: row <%s>: incompatible=%u overlap=%g rowlen=%d baserowlen=%d score=%g\n",
2814 /* we also count variables that have no arc -- these have no capacity constraint --> uncapacitated */
3167 /* for each node s, count for each other node t the number of flow variables that are not yet assigned
3170 for( v = 0; n < nflowcands; v++ ) /*lint !e440*/ /* for flexelint: n is used as abort criterion for loop */
3182 SCIPdebugMessage(" node %d starts with flowcand %d: <%s>\n", v, n, SCIProwGetName(rows[sortedflowcands[n]]));
3196 /* update sourcecount and targetcount for all flow columns in the row that are not yet assigned to an arc */
3249 * Note: each column can be collected at most once for node v, because each column can appear in at most one
3250 * commodity, and in each commodity a column can have at most one +1 and one -1 entry. One of the two +/-1 entries
3269 /* if other node has been seen the first time, store it in adjlist for sparse access of count arrays */
3317 SCIPdebugMessage(" -> assign arcid:%i to column <%s>\n", arcid, SCIPvarGetName(SCIPcolGetVar(cols[c])));
3355 SCIPdebugMessage(" -> assign arcid:%i to column <%s>\n", arcid, SCIPvarGetName(SCIPcolGetVar(cols[c])));
3375 /* mark the incident columns that could not be assigned to a new arc such that we do not inspect them again */
3400 MCFdebugMessage("network after finding uncapacitated arcs has %d nodes, %d arcs, and %d commodities\n",
3443 MCFdebugMessage("network before cleanup has %d nodes, %d arcs, and %d commodities\n", nnodes, narcs, ncommodities);
3560 SCIPdebugMessage(" -> discarding %d of %d commodities\n", ncommodities - newncommodities, ncommodities);
3696 assert(rownodeid[r] >= 0); /* otherwise we would have deleted the commodity in the rowcommodity update above */
3717 MCFdebugMessage("network after cleanup has %d nodes, %d arcs, and %d commodities\n", nnodes, narcs, ncommodities);
3971 /* in the undirected model, we use source for the maximum and target for the second largest number of total hits */
4020 SCIPdebugMessage("arc %d: %d -> %d (len=%d, sourcecnt=%g/%g, targetcnt=%g/%g, %g/%g inconsistencies)\n",
4054 MCFdebugMessage("extracted network has %g inconsistencies (ratio %g) -> separating with effort %d\n",
4237 * 2. Sort flow conservation candidates by a ranking on how sure we are that it is indeed a constraint of the desired type.
4243 * (iii) For the newly added columns search for an incident flow conservation constraint. Pick the one of highest ranking.
4248 * 5. Sort capacity constraint candidates by a ranking on how sure we are that it is indeed a constraint of the desired type.
4249 * 6. Identify capacity constraints for the arcs and assign arc ids to columns and capacity constraints.
4304 * 2. Sort flow conservation candidates by a ranking on how sure we are that it is indeed a constraint of the desired type
4333 * 5. sort capacity constraint candidates by a ranking on how sure we are that it is indeed a constraint of the desired type
4346 /* 6. arc-detection -- identify capacity constraints for the arcs and assign arc ids to columns and capacity constraints */
4417 SCIP_CALL( identifyComponent(scip, &mcfdata, nodevisited, v, compnodes, &ncompnodes, comparcs, &ncomparcs) );
4442 SCIP_CALL( mcfnetworkFill(scip, mcfnetwork, &mcfdata, compnodeid, compnodes, ncompnodes, comparcs, ncomparcs) );
4457 SCIPdebugMessage(" -> discarded network with %d nodes and %d arcs due to maxnetworks (minnodes=%d)\n",
4466 SCIPdebugMessage(" -> discarded component with %d nodes and %d arcs\n", ncompnodes, ncomparcs);
4657 MCFdebugMessage(" nof flowvars: %5d of which [ %d , %d , %d ] are continuous, integer, binary\n",
4659 MCFdebugMessage(" nof capvars: %5d of which [ %d , %d , %d ] are continuous, integer, binary\n",
4847 /* For every nodepair that is used in the network (at least one arc exists having this nodepair as endnodes)
4913 SCIPdebugMessage("arc %i = (%i %i)\n", a, mcfnetwork->arcsources[a], mcfnetwork->arctargets[a]);
4968 SCIPdebugMessage(" col <%s>: %g\n", SCIPvarGetName(SCIPcolGetVar(rowcols[i])), SCIPcolGetPrimsol(rowcols[i]) );
4972 SCIPdebugMessage(" flow col <%s>: %g\n", SCIPvarGetName(SCIPcolGetVar(rowcols[i])), REALABS(SCIPcolGetPrimsol(rowcols[i])) );
4977 SCIPdebugMessage(" cap col <%s>: %g\n", SCIPvarGetName(SCIPcolGetVar(rowcols[i])), REALABS(SCIPcolGetPrimsol(rowcols[i])) );
4982 SCIPdebugMessage("cap arc -- slack:%g -- dual:%g -- flow:%g -- cap:%g \n", scale * slack, dualsol/scale, totalflow * scale, totalcap * scale);
5019 SCIPdebugMessage("nodepair known [%d,%d] -- old weight:%g -- new weight:%g\n", nodepair.node1,nodepair.node2,nodepairptr->weight,
5032 SCIPdebugMessage("new nodepair [%d,%d]-- weight:%g\n", nodepair.node1, nodepair.node2, nodepair.weight);
5147 SCIP_CALL( SCIPpqueueInsert((*nodepairqueue)->pqueue, (void*)&(*nodepairqueue)->nodepairs[n]) );
5182 /** removes the top element from the nodepair priority queue, returns nodepair entry or NULL */
5243 SCIP_CALL( SCIPallocMemoryArray(scip, &(*nodepartition)->representatives, mcfnetwork->nnodes) );
5287 SCIPdebugMessage("shrinking nodepair (%d,%d) with weight %g: join representatives %d and %d\n",
5296 /* if there have been too few arcs to shrink the graph to the required number of clusters, join clusters with first cluster
5459 if( nodeInPartition(nodepartition, partition, FALSE, s) == nodeInPartition(nodepartition, partition, FALSE, t) )
5567 (void) SCIPsnprintf(label, SCIP_MAXSTRLEN, "%s", SCIProwGetName(mcfnetwork->nodeflowrows[v][0]));
5692 (void) SCIPsnprintf(label, SCIP_MAXSTRLEN, "%s", SCIProwGetName(mcfnetwork->arccapacityrows[a]));
5724 fprintf(file, " source %d\n", mcfnetwork->arcsources[a] >= 0 ? mcfnetwork->arcsources[a] : mcfnetwork->nnodes);
5725 fprintf(file, " target %d\n", mcfnetwork->arctargets[a] >= 0 ? mcfnetwork->arctargets[a] : mcfnetwork->nnodes);
5833 cutname, cutrhs, SCIPgetRowSolActivity(scip, cut, sol), SCIPgetCutEfficacy(scip, sol, cut), SCIProwGetRank(cut));
5850 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, NULL, sepa, ncutvars, cutvars, cutvals, +1.0, cutrhs, sol, cutoff, ncuts) );
5933 * (1) \sum_{a \in \delta^+(v)} f_a^k - \sum_{a \in \delta^-(v)} f_a^k <= -d_v^k for all v \in V and k \in K
5946 * Then, the base constraint of the c-MIR cut is the sum of those flow conservation constraints and the
5949 * sum_{k \in K^+} sum_{v \in S} (sum_{a \in \delta^+(v)} f_a^k - sum_{a \in \delta^-(v)} f_a^k) <= sum_{k \in K^+} sum_{v \in S} -d_v^k
5965 SCIPdebugMessage("maxtestdelta: %d, maxsepacuts: %d, nnodes: %d \n", maxtestdelta, maxsepacuts, nnodes);
5975 SCIPdebugMessage("maxtestdelta: %d, maxsepacuts: %d, nclusters: %d \n", maxtestdelta, maxsepacuts, nclusters);
5977 /* We fix the last cluster to belong to partition T. In the undirected case, this is sufficient,
5978 * because S-T is equivalent to T-S. In the directed case, the loop below is conducted two times,
5986 for( partition = startpartition; partition <= allpartitions-1 && !SCIPisStopped(scip) && *ncuts < maxsepacuts && !*cutoff; partition++ )
6002 if( nodepartition != NULL && !nodepartitionIsConnected(scip, mcfnetwork, nodepartition, partition ) )
6018 SCIPdebugMessage("generating single-node cuts for node %u (inverted: %u)\n", partition, inverted);
6022 SCIPdebugMessage("generating cluster cuts for partition 0x%x (inverted: %u)\n", partition, inverted);
6076 if( sepadata->separatesinglenodecuts && nodepartition != NULL && (nnodesinS == 1 || nnodesinS == nnodes-1) )
6178 SCIPdebugMessage(" -> arc %d, r=%d, capacity row <%s>: weight=%g slack=%g dual=%g\n", a, r, SCIProwGetName(arccapacityrows[a]), rowweights[r],
6185 baserhs += rowweights[r] * (SCIProwGetRhs(arccapacityrows[a]) - SCIProwGetConstant(arccapacityrows[a]));
6187 baserhs += rowweights[r] * (SCIProwGetLhs(arccapacityrows[a]) - SCIProwGetConstant(arccapacityrows[a]));
6190 /* extract useful deltas for c-MIR scaling and update the demand value for commodities (in binary flow model) */
6211 if( !SCIPisZero(scip, 1.0 / coef) && !SCIPisFeasZero(scip, coef) && SCIPcolIsIntegral(rowcols[j]) )
6268 /* if commodity was not hit by the capacity constraints of the cut in the graph, ignore the commodity */
6332 SCIPdebugMessage(" -> node %d, commodity %d, r=%d, flow row <%s>: scale=%g weight=%g slack=%g dual=%g\n",
6339 baserhs += rowweights[r] * (SCIProwGetRhs(nodeflowrows[v][k]) - SCIProwGetConstant(nodeflowrows[v][k]));
6341 baserhs += rowweights[r] * (SCIProwGetLhs(nodeflowrows[v][k]) - SCIProwGetConstant(nodeflowrows[v][k]));
6380 SCIP_CALL( SCIPcalcMIR(scip, sol, BOUNDSWITCH, USEVBDS, ALLOWLOCAL, sepadata->fixintegralrhs, NULL, NULL,
6381 (int)MAXAGGRLEN(nvars), sepadata->maxweightrange, MINFRAC, MAXFRAC, rowweights, NULL, 1.0/deltas[d],
6406 SCIP_CALL( addCut(scip, sepa, sepadata, sol, cutcoefs, cutrhs, cutislocal, cutrank, ncuts, cutoff) );
6424 SCIPgetRowFeasibility(scip, arccapacityrows[a]) * arccapacityscales[a], SCIProwGetDualsol(arccapacityrows[a]));
6542 SCIPdebugMessage(" -> discarding capacity row <%s> of weight %g and slack %g: increases MIR violation by %g\n",
6543 SCIProwGetName(arccapacityrows[a]), rowweights[r], SCIPgetRowFeasibility(scip, arccapacityrows[a]),
6564 SCIPdebugMessage("applying MIR with delta = %g to flowcut inequality (violation improvement: %g)\n", bestdelta, totalviolationdelta);
6565 SCIP_CALL( SCIPcalcMIR(scip, sol, BOUNDSWITCH, USEVBDS, ALLOWLOCAL, sepadata->fixintegralrhs, NULL, NULL,
6566 (int)MAXAGGRLEN(nvars), sepadata->maxweightrange, MINFRAC, MAXFRAC, rowweights, NULL, 1.0/bestdelta, NULL, NULL,
6573 SCIP_CALL( addCut(scip, sepa, sepadata, sol, cutcoefs, cutrhs, cutislocal, cutrank, ncuts, cutoff) );
6624 /* Notice that in principle we should have most of the columns in the LP to be able to detect a structure */
6646 /* if separation was not delayed before and we had no success in previous round then delay the separation*/
6655 MCFdebugMessage("%d columns, %d rows, ratio %g is not in [%g,%g] -> exit\n", ncols, nrows, colrowratio, MINCOLROWRATIO, MAXCOLROWRATIO);
6666 SCIP_CALL( mcfnetworkExtract(scip, sepadata, &sepadata->mcfnetworks, &sepadata->nmcfnetworks, &sepadata->effortlevel) );
6672 MCFdebugMessage(" -> extracted network %d has %d nodes, %d (%d) arcs (uncapacitated), and %d commodities (modeltype: %s)\n",
6673 i, sepadata->mcfnetworks[i]->nnodes, sepadata->mcfnetworks[i]->narcs, sepadata->mcfnetworks[i]->nuncapacitatedarcs,
6675 sepadata->mcfnetworks[i]->modeltype == SCIP_MCFMODELTYPE_DIRECTED ? "directed" : "undirected");
6710 /* do not allow networks exceeding the arcs/nodes ratio ( = average node degree / 2 (directed)) */
6721 SCIP_CALL( generateClusterCuts(scip, sepa, sepadata, sol, mcfnetwork, NULL, &ncuts, &cutoff) );
6728 sepadata->effortlevel == MCFEFFORTLEVEL_DEFAULT ? sepadata->nclusters : 2 * sepadata->nclusters) );
6734 SCIP_CALL( generateClusterCuts(scip, sepa, sepadata, sol, mcfnetwork, nodepartition, &ncuts, &cutoff) );
6740 MCFdebugMessage("MCF network has %d nodes, %d arcs, %d commodities. Found %d MCF network cuts, cutoff = %u.\n",
6799 /** solving process initialization method of separator (called when branch and bound process is about to begin) */
6817 /** solving process deinitialization method of separator (called before branch and bound process data is freed) */
6904 SCIP_CALL( SCIPincludeSepaBasic(scip, &sepa, SEPA_NAME, SEPA_DESC, SEPA_PRIORITY, SEPA_FREQ, SEPA_MAXBOUNDDIST,
6923 &sepadata->nclusters, TRUE, DEFAULT_NCLUSTERS, 2, (int) (8*sizeof(unsigned int)), NULL, NULL) );
6954 "maximal number of mcf cuts separated per separation round in the root node -- default separation",
6959 &sepadata->maxinconsistencyratio, TRUE, DEFAULT_MAXINCONSISTENCYRATIO, 0.0, SCIP_REAL_MAX, NULL, NULL) );
6963 &sepadata->maxarcinconsistencyratio, TRUE, DEFAULT_MAXARCINCONSISTENCYRATIO, 0.0, SCIP_REAL_MAX, NULL, NULL) );
static SCIP_RETCODE mcfnetworkCreate(SCIP *scip, SCIP_MCFNETWORK **mcfnetwork) Definition: sepa_mcf.c:277 Definition: type_result.h:33 SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol) Definition: scip.c:25984 static SCIP_RETCODE extractFlowRows(SCIP *scip, MCFDATA *mcfdata) Definition: sepa_mcf.c:826 static void fixCommoditySigns(SCIP *scip, MCFDATA *mcfdata) Definition: sepa_mcf.c:2950 Definition: type_result.h:34 SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol) Definition: scip.c:25961 static SCIP_RETCODE separateCuts(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result) Definition: sepa_mcf.c:6593 Definition: struct_scip.h:52 void SCIPsortInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len) SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element) Definition: misc.c:1374 Definition: sepa_mcf.c:130 static SCIP_RETCODE nodepairqueueCreate(SCIP *scip, SCIP_MCFNETWORK *mcfnetwork, NODEPAIRQUEUE **nodepairqueue) Definition: sepa_mcf.c:4841 static SCIP_RETCODE identifySourcesTargets(SCIP *scip, MCFDATA *mcfdata, SCIP_SEPADATA *sepadata, MCFEFFORTLEVEL *effortlevel) Definition: sepa_mcf.c:3724 SCIP_Real SCIPgetRowFeasibility(SCIP *scip, SCIP_ROW *row) Definition: scip.c:25941 Definition: struct_misc.h:63 Definition: sepa_mcf.c:138 static SCIP_RETCODE extractFlow(SCIP *scip, MCFDATA *mcfdata, SCIP_Real maxflowvarflowrowratio, SCIP_Bool *failed) Definition: sepa_mcf.c:2031 SCIP_Bool SCIPisCutEfficacious(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut) Definition: scip.c:28148 SCIP_RETCODE SCIPseparateRelaxedKnapsack(SCIP *scip, SCIP_CONS *cons, SCIP_SEPA *sepa, int nknapvars, SCIP_VAR **knapvars, SCIP_Real *knapvals, SCIP_Real valscale, SCIP_Real rhs, SCIP_SOL *sol, SCIP_Bool *cutoff, int *ncuts) Definition: cons_knapsack.c:5737 Definition: struct_var.h:196 static SCIP_RETCODE extractCapacities(SCIP *scip, MCFDATA *mcfdata) Definition: sepa_mcf.c:2225 static SCIP_RETCODE identifyComponent(SCIP *scip, MCFDATA *mcfdata, int *nodevisited, int startv, int *compnodes, int *ncompnodes, int *comparcs, int *ncomparcs) Definition: sepa_mcf.c:4073 static SCIP_RETCODE nodepartitionCreate(SCIP *scip, SCIP_MCFNETWORK *mcfnetwork, NODEPARTITION **nodepartition, int nclusters) Definition: sepa_mcf.c:5223 static void nodepairqueueFree(SCIP *scip, NODEPAIRQUEUE **nodepairqueue) Definition: sepa_mcf.c:5156 Definition: type_var.h:53 static SCIP_RETCODE getNodeSimilarityScore(SCIP *scip, MCFDATA *mcfdata, int baserowlen, int *basearcpattern, int basenposuncap, int basenneguncap, SCIP_ROW *row, SCIP_Real *score, SCIP_Bool *invertcommodity) Definition: sepa_mcf.c:2477 static NODEPAIRENTRY * nodepairqueueRemove(NODEPAIRQUEUE *nodepairqueue) Definition: sepa_mcf.c:5184 SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var) Definition: scip.c:31775 Definition: type_result.h:40 Definition: struct_sepa.h:36 SCIP_RETCODE SCIPaddCut(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool *infeasible) Definition: scip.c:28256 SCIP_RETCODE SCIPsetSepaFree(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAFREE((*sepafree))) Definition: scip.c:6440 static SCIP_RETCODE mcfnetworkExtract(SCIP *scip, SCIP_SEPADATA *sepadata, SCIP_MCFNETWORK ***mcfnetworks, int *nmcfnetworks, MCFEFFORTLEVEL *effortlevel) Definition: sepa_mcf.c:4204 static SCIP_RETCODE addCut(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata, SCIP_SOL *sol, SCIP_Real *cutcoefs, SCIP_Real cutrhs, SCIP_Bool cutislocal, int cutrank, int *ncuts, SCIP_Bool *cutoff) Definition: sepa_mcf.c:5757 SCIP_RETCODE SCIPsetSepaInitsol(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAINITSOL((*sepainitsol))) Definition: scip.c:6488 SCIP_RETCODE SCIPgetLPColsData(SCIP *scip, SCIP_COL ***cols, int *ncols) Definition: scip.c:24369 SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr) Definition: misc.c:1287 Definition: struct_lp.h:123 Definition: struct_sol.h:50 SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata) Definition: scip.c:3388 static SCIP_RETCODE findUncapacitatedArcs(SCIP *scip, MCFDATA *mcfdata) Definition: sepa_mcf.c:3067 SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata) Definition: scip.c:3414 static void getIncidentNodes(SCIP *scip, MCFDATA *mcfdata, SCIP_COL *col, int *sourcenode, int *targetnode) Definition: sepa_mcf.c:2968 Constraint handler for knapsack constraints of the form , x binary and . Definition: type_result.h:35 static void unionfindJoinSets(int *representatives, int rep1, int rep2) Definition: sepa_mcf.c:4711 void SCIPsortIntInt(int *intarray1, int *intarray2, int len) static SCIP_Bool nodeInPartition(NODEPARTITION *nodepartition, unsigned int partition, SCIP_Bool inverted, int v) Definition: sepa_mcf.c:5390 SCIP_RETCODE SCIPcalcMIR(SCIP *scip, SCIP_SOL *sol, SCIP_Real boundswitch, SCIP_Bool usevbds, SCIP_Bool allowlocal, SCIP_Bool fixintegralrhs, int *boundsfortrans, SCIP_BOUNDTYPE *boundtypesfortrans, int maxmksetcoefs, SCIP_Real maxweightrange, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Real *weights, int *sidetypes, SCIP_Real scale, SCIP_Real *mksetcoefs, SCIP_Bool *mksetcoefsvalid, SCIP_Real *mircoef, SCIP_Real *mirrhs, SCIP_Real *cutactivity, SCIP_Bool *success, SCIP_Bool *cutislocal, int *cutrank) Definition: scip.c:24743 static void nodepartitionJoin(NODEPARTITION *nodepartition, int rep1, int rep2) Definition: sepa_mcf.c:5212 static SCIP_RETCODE createNewArc(SCIP *scip, MCFDATA *mcfdata, int source, int target, int *newarcid) Definition: sepa_mcf.c:1434 SCIP_Real SCIPgetRowLPFeasibility(SCIP *scip, SCIP_ROW *row) Definition: scip.c:25827 static int nodepartitionIsConnected(SCIP *scip, SCIP_MCFNETWORK *mcfnetwork, NODEPARTITION *nodepartition, unsigned int partition) Definition: sepa_mcf.c:5420 Definition: type_retcode.h:33 SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows) Definition: scip.c:24447 static SCIP_RETCODE cleanupNetwork(SCIP *scip, MCFDATA *mcfdata) Definition: sepa_mcf.c:3408 Definition: sepa_mcf.c:128 Definition: sepa_mcf.c:137 SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2) Definition: scip.c:38705 SCIP_RETCODE SCIPcreateEmptyRowSepa(SCIP *scip, SCIP_ROW **row, SCIP_SEPA *sepa, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable) Definition: scip.c:25305 static SCIP_RETCODE mcfnetworkFill(SCIP *scip, SCIP_MCFNETWORK *mcfnetwork, MCFDATA *mcfdata, int *compnodeid, int *compnodes, int ncompnodes, int *comparcs, int ncomparcs) Definition: sepa_mcf.c:354 Definition: type_lp.h:34 static void collectIncidentFlowCols(SCIP *scip, MCFDATA *mcfdata, SCIP_ROW *flowrow, int basecommodity) Definition: sepa_mcf.c:2391 public data structures and miscellaneous methods multi-commodity-flow network cut separator Definition: type_var.h:55 SCIP_RETCODE SCIPsetSepaCopy(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPACOPY((*sepacopy))) Definition: scip.c:6424 SCIP_RETCODE SCIPsetSepaExitsol(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAEXITSOL((*sepaexitsol))) Definition: scip.c:6504 Definition: type_var.h:54 SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row) Definition: scip.c:25487 Definition: struct_lp.h:188 static SCIP_RETCODE generateClusterCuts(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata, SCIP_SOL *sol, SCIP_MCFNETWORK *mcfnetwork, NODEPARTITION *nodepartition, int *ncuts, SCIP_Bool *cutoff) Definition: sepa_mcf.c:5864 static void deleteCommodity(SCIP *scip, MCFDATA *mcfdata, int k, SCIP_ROW **comrows, int nrows, int *ndelflowrows, int *ndelflowvars) Definition: sepa_mcf.c:1698 void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key) Definition: misc.c:1434 Definition: type_retcode.h:39 static void getNextFlowrow(SCIP *scip, MCFDATA *mcfdata, SCIP_ROW **nextrow, unsigned char *nextrowsign, SCIP_Bool *nextinvertcommodity) Definition: sepa_mcf.c:1914 static SCIP_RETCODE mcfnetworkFree(SCIP *scip, SCIP_MCFNETWORK **mcfnetwork) Definition: sepa_mcf.c:303 Definition: sepa_mcf.c:129 Definition: struct_misc.h:80 SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row) Definition: scip.c:25510 SCIP_RETCODE SCIPpqueueInsert(SCIP_PQUEUE *pqueue, void *elem) Definition: misc.c:798 static int nodepartitionGetRepresentative(NODEPARTITION *nodepartition, int v) Definition: sepa_mcf.c:5202 void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...) Definition: scip.c:1239 SCIP_RETCODE SCIPpqueueCreate(SCIP_PQUEUE **pqueue, int initsize, SCIP_Real sizefac, SCIP_DECL_SORTPTRCOMP((*ptrcomp))) Definition: misc.c:752 static SCIP_RETCODE extractCapacityRows(SCIP *scip, MCFDATA *mcfdata) Definition: sepa_mcf.c:1042 static void getFlowrowFit(SCIP *scip, MCFDATA *mcfdata, SCIP_ROW *row, int k, unsigned char *rowsign, SCIP_Bool *invertcommodity) Definition: sepa_mcf.c:1782 Definition: sepa_mcf.c:144 SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars) Definition: scip.c:9945 static SCIP_Bool nodepairqueueIsEmpty(NODEPAIRQUEUE *nodepairqueue) Definition: sepa_mcf.c:5172 static void unionfindInitSets(int *representatives, int nelems) Definition: sepa_mcf.c:4679 SCIP_RETCODE SCIPincludeSepaBasic(SCIP *scip, SCIP_SEPA **sepa, const char *name, const char *desc, int priority, int freq, SCIP_Real maxbounddist, SCIP_Bool usessubscip, SCIP_Bool delay, SCIP_DECL_SEPAEXECLP((*sepaexeclp)), SCIP_DECL_SEPAEXECSOL((*sepaexecsol)), SCIP_SEPADATA *sepadata) Definition: scip.c:6382 Definition: type_retcode.h:43 static void invertCommodity(SCIP *scip, MCFDATA *mcfdata, int k, SCIP_ROW **comrows, int ncomrows, int *comcolids, int ncomcolids) Definition: sepa_mcf.c:1633 SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata) Definition: scip.c:3470 static int unionfindGetRepresentative(int *representatives, int v) Definition: sepa_mcf.c:4693 SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val) Definition: scip.c:25540 SCIP_Real SCIPgetCutEfficacy(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut) Definition: scip.c:28125 static void addFlowrowToCommodity(SCIP *scip, MCFDATA *mcfdata, SCIP_ROW *row, unsigned char rowsign, int *comcolids, int *ncomcolids) Definition: sepa_mcf.c:1487 static SCIP_RETCODE extractNodes(SCIP *scip, MCFDATA *mcfdata) Definition: sepa_mcf.c:2679 Definition: type_result.h:39 Definition: sepa_mcf.c:139 static void nodepartitionFree(SCIP *scip, NODEPARTITION **nodepartition) Definition: sepa_mcf.c:5373 static SCIP_RETCODE createNewCommodity(SCIP *scip, MCFDATA *mcfdata) Definition: sepa_mcf.c:1410 Definition: type_var.h:56 |