46 #define BETTERWEIGHTFORDEMANDNODES 56 #define SEPA_NAME "mcf" 57 #define SEPA_DESC "multi-commodity-flow network cut separator" 58 #define SEPA_PRIORITY -10000 60 #define SEPA_MAXBOUNDDIST 0.0 61 #define SEPA_USESSUBSCIP FALSE 62 #define SEPA_DELAY FALSE 65 #define DEFAULT_NCLUSTERS 5 66 #define DEFAULT_MAXWEIGHTRANGE 1e+06 67 #define DEFAULT_MAXTESTDELTA 20 68 #define DEFAULT_TRYNEGSCALING FALSE 69 #define DEFAULT_FIXINTEGRALRHS TRUE 70 #define DEFAULT_DYNAMICCUTS TRUE 71 #define DEFAULT_MODELTYPE 0 72 #define DEFAULT_MAXSEPACUTS 100 73 #define DEFAULT_MAXSEPACUTSROOT 200 74 #define DEFAULT_MAXINCONSISTENCYRATIO 0.02 75 #define DEFAULT_MAXARCINCONSISTENCYRATIO 0.5 76 #define DEFAULT_CHECKCUTSHORECONNECTIVITY TRUE 77 #define DEFAULT_SEPARATESINGLENODECUTS TRUE 78 #define DEFAULT_SEPARATEFLOWCUTSET TRUE 79 #define DEFAULT_SEPARATEKNAPSACK TRUE 82 #define BOUNDSWITCH 0.5 84 #define ALLOWLOCAL TRUE 88 #define MAXCOLS 2000000 89 #define MAXAGGRLEN(nvars) (0.1*(nvars)+1000) 90 #define MINCOLROWRATIO 0.01 91 #define MAXCOLROWRATIO 100.0 92 #define MAXFLOWVARFLOWROWRATIO 100.0 93 #define MAXARCNODERATIO 100.0 95 #define MAXFLOWCANDDENSITY 0.1 96 #define MINCOMNODESFRACTION 0.5 99 #define MAXCAPACITYSLACK 0.1 100 #define UNCAPACITATEDARCSTRESHOLD 0.8 101 #define HASHSIZE_NODEPAIRS 131101 113 #define MCFdebugMessage printf 117 #define MCFdebugMessage while(FALSE) printf 191 unsigned char* flowrowsigns;
194 unsigned char* capacityrowsigns;
203 int nemptycommodities;
205 int commoditysignssize;
226 int capacityrowssize;
253 int* representatives;
265 #define LHSPOSSIBLE 1u 266 #define RHSPOSSIBLE 2u 267 #define LHSASSIGNED 4u 268 #define RHSASSIGNED 8u 270 #define DISCARDED 32u 271 #define UNDIRECTED 64u 281 assert(mcfnetwork !=
NULL);
284 (*mcfnetwork)->nodeflowrows =
NULL;
285 (*mcfnetwork)->nodeflowscales =
NULL;
286 (*mcfnetwork)->nodeflowinverted =
NULL;
287 (*mcfnetwork)->arccapacityrows =
NULL;
288 (*mcfnetwork)->arccapacityscales =
NULL;
289 (*mcfnetwork)->arcsources =
NULL;
290 (*mcfnetwork)->arctargets =
NULL;
291 (*mcfnetwork)->colcommodity =
NULL;
292 (*mcfnetwork)->nnodes = 0;
293 (*mcfnetwork)->nuncapacitatedarcs = 0;
294 (*mcfnetwork)->narcs = 0;
295 (*mcfnetwork)->ncommodities = 0;
307 assert(mcfnetwork !=
NULL);
309 if( *mcfnetwork !=
NULL )
314 for( v = 0; v < (*mcfnetwork)->nnodes; v++ )
318 for( k = 0; k < (*mcfnetwork)->ncommodities; k++ )
320 if( (*mcfnetwork)->nodeflowrows[v][k] !=
NULL )
329 for( a = 0; a < (*mcfnetwork)->narcs; a++ )
331 if( (*mcfnetwork)->arccapacityrows[a] !=
NULL )
364 unsigned char* flowrowsigns = mcfdata->flowrowsigns;
365 SCIP_Real* flowrowscalars = mcfdata->flowrowscalars;
366 unsigned char* capacityrowsigns = mcfdata->capacityrowsigns;
367 int* flowcands = mcfdata->flowcands;
368 int nflowcands = mcfdata->nflowcands;
370 int* commoditysigns = mcfdata->commoditysigns;
372 int* rowcommodity = mcfdata->rowcommodity;
373 int* rownodeid = mcfdata->rownodeid;
374 SCIP_ROW** capacityrows = mcfdata->capacityrows;
383 int ncompcommodities;
390 assert(mcfnetwork !=
NULL);
392 assert(2 <= ncompnodes && ncompnodes <= mcfdata->
nnodes);
393 assert(1 <= ncomparcs && ncomparcs <= mcfdata->
narcs);
394 assert(ncommodities > 0);
398 for( v = 0; v < mcfdata->nnodes; v++ )
399 assert(compnodeid[v] == -1);
411 compcommodity[k] = -1;
418 for( i = 0; i < ncompnodes; i++ )
421 assert(0 <= v && v < mcfdata->nnodes);
426 ncompcommodities = 0;
427 for( i = 0; i < nflowcands; i++ )
433 assert(0 <= r && r < nrows);
436 if( rv >= 0 && compnodeid[rv] >= 0 )
439 assert(0 <= k && k < ncommodities);
440 if( compcommodity[k] == -1 )
442 compcommodity[k] = ncompcommodities;
453 mcfnetwork->
nnodes = ncompnodes;
454 mcfnetwork->
narcs = ncomparcs;
462 for( v = 0; v < mcfnetwork->
nnodes; v++ )
480 for( a = 0; a < mcfnetwork->
narcs; a++ )
490 for( i = 0; i < nflowcands; i++ )
496 assert(0 <= r && r < nrows);
499 if( rv >= 0 && compnodeid[rv] >= 0 )
505 rk = rowcommodity[r];
506 assert(v < mcfnetwork->nnodes);
507 assert(0 <= rk && rk < ncommodities);
510 k = compcommodity[rk];
511 assert(0 <= k && k < mcfnetwork->ncommodities);
516 scale = flowrowscalars[r];
519 if( commoditysigns[rk] == -1 )
527 for( a = 0; a < mcfnetwork->
narcs; a++ )
537 globala = comparcs[a];
538 capacityrow = capacityrows[globala];
543 if( capacityrow !=
NULL)
546 assert(0 <= r && r < nrows);
548 assert((capacityrowsigns[r] &
INVERTED) == 0);
549 assert(mcfdata->rowarcid[r] == globala);
567 for( j = 0; j < rowlen; j++ )
574 if( comdemands[k] != 0.0 )
589 for( j = 0; j < rowlen; j++ )
594 if( k >= 0 && comdemands[k] == 0.0 )
606 if( mcfdata->arcsources[globala] >= 0 )
608 assert(mcfdata->arcsources[globala] < mcfdata->nnodes);
609 assert(0 <= compnodeid[mcfdata->arcsources[globala]] && compnodeid[mcfdata->arcsources[globala]] < mcfnetwork->
nnodes);
610 mcfnetwork->
arcsources[a] = compnodeid[mcfdata->arcsources[globala]];
612 if( mcfdata->arctargets[globala] >= 0 )
614 assert(mcfdata->arctargets[globala] < mcfdata->nnodes);
615 assert(0 <= compnodeid[mcfdata->arctargets[globala]] && compnodeid[mcfdata->arctargets[globala]] < mcfnetwork->
nnodes);
616 mcfnetwork->
arctargets[a] = compnodeid[mcfdata->arctargets[globala]];
621 for( c = 0; c < ncols; c++ )
631 for( i = 0; i < ncompnodes; i++ )
633 assert(0 <= compnodes[i] && compnodes[i] < mcfdata->nnodes);
634 assert(compnodeid[compnodes[i]] == i);
635 compnodeid[compnodes[i]] = -1;
648 void mcfnetworkPrint(
652 if( mcfnetwork ==
NULL )
659 for( v = 0; v < mcfnetwork->
nnodes; v++ )
678 for( a = 0; a < mcfnetwork->
narcs; a++ )
694 void printCommodities(
699 unsigned char* flowrowsigns = mcfdata->flowrowsigns;
700 unsigned char* capacityrowsigns = mcfdata->capacityrowsigns;
702 int* commoditysigns = mcfdata->commoditysigns;
704 int* rowcommodity = mcfdata->rowcommodity;
705 int* colarcid = mcfdata->colarcid;
706 int* rownodeid = mcfdata->rownodeid;
707 int nnodes = mcfdata->nnodes;
708 SCIP_ROW** capacityrows = mcfdata->capacityrows;
728 for( c = 0; c < ncols; c++ )
730 if( colcommodity[c] == k )
733 for( r = 0; r < nrows; r++ )
735 if( rowcommodity[r] == k )
738 (flowrowsigns[r] &
INVERTED) != 0 ? -1 : +1);
743 if( rownodeid !=
NULL )
747 for( v = 0; v <
nnodes; v++ )
750 for( r = 0; r < nrows; r++ )
752 if( rownodeid[r] == v )
755 (flowrowsigns[r] &
INVERTED) != 0 ? -1 : +1);
761 assert(capacityrows !=
NULL || mcfdata->narcs == 0);
764 for( a = 0; a < mcfdata->narcs; a++ )
767 if( capacityrows[a] !=
NULL )
770 assert(0 <= r && r < nrows);
773 else if( (capacityrowsigns[r] &
RHSASSIGNED) != 0 )
781 assert(colcommodity !=
NULL || ncols == 0);
784 for( c = 0; c < ncols; c++ )
786 if( colcommodity[c] == -1 )
795 for( r = 0; r < nrows; r++ )
797 assert(rowcommodity !=
NULL);
815 if( rowscores[ind2] < rowscores[ind1] )
817 else if( rowscores[ind2] > rowscores[ind1] )
830 unsigned char* flowrowsigns;
850 flowrowsigns = mcfdata->flowrowsigns;
851 flowrowscalars = mcfdata->flowrowscalars;
852 flowrowscores = mcfdata->flowrowscores;
853 flowcands = mcfdata->flowcands;
855 assert(mcfdata->nflowcands == 0);
858 for( r = 0; r < nrows; r++ )
883 absdualsol = ABS(absdualsol);
886 flowrowscalars[r] = 0.0;
887 flowrowscores[r] = 0.0;
908 coef = ABS(rowvals[0]);
915 for( i = 0; i < rowlen; i++ )
921 hasposcoef = hasposcoef || (rowvals[i] > 0.0);
922 hasnegcoef = hasnegcoef || (rowvals[i] < 0.0);
952 flowrowscalars[r] = 1.0/coef;
953 flowcands[mcfdata->nflowcands] = r;
954 mcfdata->nflowcands++;
961 if(
SCIPisEQ(scip, flowrowscalars[r], 1.0) )
962 flowrowscores[r] += 1000.0;
965 if( hasposcoef && hasnegcoef )
966 flowrowscores[r] += 500.0;
973 if( ncontvars == rowlen )
974 flowrowscores[r] += 1000.0;
975 else if( nintvars + nimplintvars == rowlen )
976 flowrowscores[r] += 500.0;
977 else if( nbinvars == rowlen )
978 flowrowscores[r] += 100.0;
982 flowrowscores[r] += 10.0*rowlen/(rowlen+10.0);
986 flowrowscores[r] += 50.0;
988 assert(flowrowscores[r] > 0.0);
991 maxdualflow =
MAX(maxdualflow, absdualsol);
1004 for( i = 0; i < mcfdata->nflowcands; i++ )
1009 assert(0 <= r && r < nrows);
1014 dualsol = ABS(dualsol);
1017 assert(maxdualflow > 0.0);
1018 flowrowscores[r] += dualsol/maxdualflow + 1.0;
1019 assert(flowrowscores[r] > 0.0);
1024 SCIPsortInd(mcfdata->flowcands, compCands, (
void*)flowrowscores, mcfdata->nflowcands);
1026 MCFdebugMessage(
"flow conservation candidates [%d]\n", mcfdata->nflowcands);
1028 for( r = 0; r < mcfdata->nflowcands; r++ )
1031 SCIPdebugMessage(
"%4d [score: %2g]: %s\n", mcfdata->flowcands[r], flowrowscores[mcfdata->flowcands[r]],
1046 unsigned char* flowrowsigns = mcfdata->flowrowsigns;
1049 int nactivecommodities = mcfdata->ncommodities - mcfdata->nemptycommodities;
1052 unsigned char* capacityrowsigns;
1061 int maxcolspercommoditylimit;
1062 int *ncolspercommodity;
1063 int *maxcolspercommodity;
1073 capacityrowsigns = mcfdata->capacityrowsigns;
1074 capacityrowscores = mcfdata->capacityrowscores;
1075 capacitycands = mcfdata->capacitycands;
1077 assert(mcfdata->ncapacitycands == 0);
1087 maxcolspercommoditylimit = 2;
1090 maxcolspercommoditylimit = 1;
1093 maxcolspercommoditylimit = 2;
1096 SCIPerrorMessage(
"invalid parameter value %d for model type\n", modeltype);
1100 maxdualcapacity = 0.0;
1101 directedcandsscore = 0.0;
1102 undirectedcandsscore = 0.0;
1103 for( r = 0; r < nrows; r++ )
1113 int nposcapacitycoefs;
1114 int nnegcapacitycoefs;
1116 int ncoveredcommodities;
1121 unsigned char rowsign;
1127 capacityrowsigns[r] = 0;
1128 capacityrowscores[r] = 0.0;
1147 absdualsol = ABS(absdualsol);
1156 maxcolspercommodity[r] = 0;
1161 nposcapacitycoefs = 0;
1162 nnegcapacitycoefs = 0;
1164 ncoveredcommodities = 0;
1166 sameabsflowcoef = 0.0;
1167 maxabscapacitycoef = 0.0;
1174 for( i = 0; i < rowlen; i++ )
1183 k = colcommodity[c];
1184 assert(-1 <= k && k < ncommodities);
1189 abscoef = ABS(rowvals[i]);
1190 if( sameflowcoef == 0.0 )
1191 sameflowcoef = rowvals[i];
1192 else if( !
SCIPisEQ(scip, sameflowcoef, rowvals[i]) )
1194 if( sameabsflowcoef == 0.0 )
1195 sameabsflowcoef = abscoef;
1196 else if( !
SCIPisEQ(scip, sameabsflowcoef, abscoef) )
1199 if( rowvals[i] > 0.0 )
1205 if( ncolspercommodity[k] == 0 )
1206 ncoveredcommodities++;
1207 ncolspercommodity[k]++;
1208 maxcolspercommodity[r] =
MAX(maxcolspercommodity[r], ncolspercommodity[k]);
1210 if( ncolspercommodity[k] >= 2 )
1219 abscoef = ABS(rowvals[i]);
1220 if( abscoef > maxabscapacitycoef )
1221 maxabscapacitycoef = abscoef;
1224 if( rowvals[i] > 0.0 )
1225 nposcapacitycoefs++;
1227 nnegcapacitycoefs++;
1237 if( rowsign != 0 && nposflowcoefs + nnegflowcoefs > 0 )
1241 capacityrowsigns[r] |= rowsign;
1242 capacitycands[mcfdata->ncapacitycands] = r;
1243 mcfdata->ncapacitycands++;
1246 capacityrowscores[r] = 1.0;
1250 assert(ncoveredcommodities > 0);
1251 commodityexcessratio =
1252 ABS((nposflowcoefs + nnegflowcoefs)/(
SCIP_Real)ncoveredcommodities - maxcolspercommoditylimit);
1254 capacityrowscores[r] += 1000.0 *
MAX(0.0, 2.0 - commodityexcessratio);
1261 if( (capacityrowsigns[r] &
RHSPOSSIBLE) != 0 && nnegflowcoefs == 0 && nposcapacitycoefs == 0 && nnegcapacitycoefs > 0 )
1262 capacityrowscores[r] += 1000.0;
1263 if( (capacityrowsigns[r] &
LHSPOSSIBLE) != 0 && nposflowcoefs == 0 && nposcapacitycoefs > 0 && nnegcapacitycoefs == 0 )
1264 capacityrowscores[r] += 1000.0;
1273 assert(nactivecommodities + 3 > 0);
1274 capacityrowscores[r] += 2000.0 * ncoveredcommodities/(
SCIP_Real)(nactivecommodities + 3);
1277 if(
SCIPisEQ(scip, ABS(sameflowcoef), 1.0) )
1278 capacityrowscores[r] += 500.0;
1282 capacityrowscores[r] += 250.0;
1285 if(
SCIPisEQ(scip, sameabsflowcoef, 1.0) )
1286 capacityrowscores[r] += 100.0;
1289 if( maxabscapacitycoef > 0.0 && !
SCIPisEQ(scip, maxabscapacitycoef, 1.0) )
1290 capacityrowscores[r] += 100.0;
1293 capacityrowscores[r] += 20.0 *
MAX(nposflowcoefs, nnegflowcoefs)/
MAX(1.0,(
SCIP_Real)(nposflowcoefs + nnegflowcoefs));
1296 capacityrowscores[r] += 10.0 *
MAX(nposcapacitycoefs, nnegcapacitycoefs)/(
SCIP_Real)(nposcapacitycoefs+nnegcapacitycoefs+1.0);
1299 if( (capacityrowsigns[r] & RHSPOSSIBLE) != 0 && !
SCIPisNegative(scip, rowrhs) )
1300 capacityrowscores[r] += 10.0;
1304 capacityrowscores[r] += 10.0;
1306 assert(capacityrowscores[r] > 0.0);
1307 SCIPdebugMessage(
"row <%s>: maxcolspercommodity=%d capacityrowsign=%d nposflowcoefs=%d nnegflowcoefs=%d nposcapacitycoefs=%d nnegcapacitycoefs=%d nbadcoefs=%d nactivecommodities=%d sameflowcoef=%g -> score=%g\n",
1308 SCIProwGetName(row), maxcolspercommodity[r], capacityrowsigns[r], nposflowcoefs, nnegflowcoefs, nposcapacitycoefs, nnegcapacitycoefs, nbadcoefs, nactivecommodities, sameflowcoef, capacityrowscores[r]);
1311 maxdualcapacity =
MAX(maxdualcapacity, absdualsol);
1316 assert(maxcolspercommoditylimit == 2);
1317 if( (capacityrowsigns[r] &
UNDIRECTED) != 0 )
1318 undirectedcandsscore += capacityrowscores[r];
1320 directedcandsscore += capacityrowscores[r];
1325 SCIPdebugMessage(
"row <%s>: rowsign = %d nposflowcoefs = %d nnegflowcoefs = %d -> discard\n",
1333 if( directedcandsscore > undirectedcandsscore )
1338 MCFdebugMessage(
"detected model type: %s (%g directed score, %g undirected score)\n",
1346 for( i = 0; i < mcfdata->ncapacitycands; i++ )
1348 r = capacitycands[i];
1349 assert(0 <= r && r < nrows);
1350 if( (capacityrowsigns[r] &
UNDIRECTED) != 0 )
1353 if( maxcolspercommodity[r] <= maxcolspercommoditylimit )
1354 capacityrowscores[r] -= 1000.0;
1368 for( i = 0; i < mcfdata->ncapacitycands; i++ )
1372 r = capacitycands[i];
1373 assert(0 <= r && r < nrows);
1378 dualsol = ABS(dualsol);
1381 assert(maxdualcapacity > 0.0);
1382 capacityrowscores[r] +=
MAX(dualsol, 0.0)/maxdualcapacity;
1383 assert(capacityrowscores[r] > 0.0);
1388 SCIPsortInd(mcfdata->capacitycands, compCands, (
void*)capacityrowscores, mcfdata->ncapacitycands);
1390 MCFdebugMessage(
"capacity candidates [%d]\n", mcfdata->ncapacitycands);
1392 for( r = 0; r < mcfdata->ncapacitycands; r++ )
1395 capacityrowscores[mcfdata->capacitycands[r]],
SCIProwGetName(rows[mcfdata->capacitycands[r]]));
1415 assert(mcfdata->ncommodities <= mcfdata->commoditysignssize);
1416 if( mcfdata->ncommodities == mcfdata->commoditysignssize )
1418 mcfdata->commoditysignssize =
MAX(2*mcfdata->commoditysignssize, mcfdata->ncommodities+1);
1421 assert(mcfdata->ncommodities < mcfdata->commoditysignssize);
1424 SCIPdebugMessage(
"**** creating new commodity %d ****\n", mcfdata->ncommodities);
1425 mcfdata->commoditysigns[mcfdata->ncommodities] = 0;
1426 mcfdata->ncommodities++;
1441 assert(source != target );
1442 assert(0 <= source && source < mcfdata->
nnodes);
1443 assert(0 <= target && target < mcfdata->nnodes);
1444 assert(newarcid !=
NULL);
1446 *newarcid = mcfdata->narcs;
1449 assert(mcfdata->narcs <= mcfdata->arcarraysize);
1450 if( mcfdata->narcs == mcfdata->arcarraysize )
1452 mcfdata->arcarraysize =
MAX(2*mcfdata->arcarraysize, mcfdata->narcs+1);
1458 assert(mcfdata->narcs < mcfdata->arcarraysize);
1461 if( mcfdata->capacityrowssize < mcfdata->arcarraysize )
1463 mcfdata->capacityrowssize = mcfdata->arcarraysize;
1466 assert(mcfdata->narcs < mcfdata->capacityrowssize);
1469 SCIPdebugMessage(
"**** creating new arc %d: %d -> %d ****\n", mcfdata->narcs, source, target);
1471 mcfdata->arcsources[*newarcid] = source;
1472 mcfdata->arctargets[*newarcid] = target;
1473 mcfdata->nextoutarcs[*newarcid] = mcfdata->firstoutarcs[source];
1474 mcfdata->firstoutarcs[source] = *newarcid;
1475 mcfdata->nextinarcs[*newarcid] = mcfdata->firstinarcs[target];
1476 mcfdata->firstinarcs[target] = *newarcid;
1477 mcfdata->capacityrows[*newarcid] =
NULL;
1490 unsigned char rowsign,
1495 unsigned char* flowrowsigns = mcfdata->flowrowsigns;
1496 SCIP_Bool* plusflow = mcfdata->plusflow;
1497 SCIP_Bool* minusflow = mcfdata->minusflow;
1499 int* commoditysigns = mcfdata->commoditysigns;
1501 int* rowcommodity = mcfdata->rowcommodity;
1502 int* newcols = mcfdata->newcols;
1513 assert(comcolids !=
NULL);
1514 assert(ncomcolids !=
NULL);
1523 invertrow = ((rowsign &
INVERTED) != 0);
1526 assert(rowcommodity[r] == -1);
1527 assert((flowrowsigns[r] | rowsign) == flowrowsigns[r]);
1529 assert(rowsign != 0);
1535 commoditysigns[k] = +1;
1564 else if( rowlhs > 0.0 )
1581 flowrowsigns[r] |= rowsign;
1583 SCIPdebugMessage(
"adding flow row %d <%s> with sign %+d%s to commodity %d [score:%g]\n",
1585 k, mcfdata->flowrowscores[r]);
1589 rowcommodity[r] = k;
1593 for( i = 0; i < rowlen; i++ )
1602 if( colcommodity[c] == -1 )
1604 assert(!plusflow[c]);
1605 assert(!minusflow[c]);
1607 colcommodity[c] = k;
1608 newcols[mcfdata->nnewcols] = c;
1609 mcfdata->nnewcols++;
1610 comcolids[*ncomcolids] = c;
1613 assert(colcommodity[c] == k);
1616 val = rowscale * rowvals[i];
1619 assert(!plusflow[c]);
1624 assert(!minusflow[c]);
1625 minusflow[c] =
TRUE;
1642 unsigned char* flowrowsigns = mcfdata->flowrowsigns;
1643 SCIP_Bool* plusflow = mcfdata->plusflow;
1644 SCIP_Bool* minusflow = mcfdata->minusflow;
1648 assert(mcfdata->commoditysigns[k] == 0);
1649 assert(comrows !=
NULL || ncomrows == 0);
1650 assert(comcolids !=
NULL);
1653 for( i = 0; i < ncomrows; i++ )
1657 unsigned char rowsign;
1659 assert(comrows !=
NULL);
1661 assert( row !=
NULL );
1664 assert(mcfdata->rowcommodity[r] == k);
1668 rowsign = flowrowsigns[r];
1680 for( i = 0; i < ncomcolids; i++ )
1687 assert(mcfdata->colcommodity[c] == k);
1690 plusflow[c] = minusflow[c];
1707 unsigned char* flowrowsigns = mcfdata->flowrowsigns;
1708 SCIP_Bool* plusflow = mcfdata->plusflow;
1709 SCIP_Bool* minusflow = mcfdata->minusflow;
1712 int* rowcommodity = mcfdata->rowcommodity;
1716 assert(0 <= k && k < ncommodities);
1718 assert( ndelflowrows !=
NULL );
1719 assert( ndelflowvars !=
NULL );
1721 SCIPdebugMessage(
"deleting commodity %d (%d total commodities) with %d flow rows\n", k, ncommodities, nrows);
1726 for( n = 0; n < nrows; n++ )
1737 assert(rowcommodity[r] == k);
1746 rowcommodity[r] = -1;
1749 for( i = 0; i < rowlen; i++ )
1757 assert(colcommodity[c] == k || colcommodity[c] == -1);
1758 if(colcommodity[c] == k)
1760 colcommodity[c] = -1;
1763 plusflow[c] =
FALSE;
1764 minusflow[c] =
FALSE;
1773 if( k == ncommodities-1 )
1774 mcfdata->ncommodities--;
1776 mcfdata->nemptycommodities++;
1786 unsigned char* rowsign,
1790 unsigned char* flowrowsigns = mcfdata->flowrowsigns;
1791 SCIP_Bool* plusflow = mcfdata->plusflow;
1792 SCIP_Bool* minusflow = mcfdata->minusflow;
1794 int* rowcommodity = mcfdata->rowcommodity;
1795 int* commoditysigns = mcfdata->commoditysigns;
1800 unsigned char flowrowsign;
1801 unsigned char invflowrowsign;
1805 assert(invertcommodity !=
NULL);
1808 *invertcommodity =
FALSE;
1814 if( rowcommodity[r] != -1 )
1818 flowrowsign = flowrowsigns[r];
1824 invflowrowsign = flowrowsign;
1830 for( j = 0; j < rowlen && (flowrowsign != 0 || invflowrowsign != 0); j++ )
1838 if( colcommodity[rowc] == k )
1841 if( plusflow[rowc] )
1844 if( rowvals[j] > 0.0 )
1855 if( minusflow[rowc] )
1858 if( rowvals[j] > 0.0 )
1870 else if( colcommodity[rowc] != -1 )
1878 if( flowrowsign != 0 )
1881 *rowsign = flowrowsign;
1882 *invertcommodity =
FALSE;
1884 else if( invflowrowsign != 0 )
1890 if( commoditysigns ==
NULL || commoditysigns[k] == 0 )
1893 *rowsign = invflowrowsign;
1894 *invertcommodity =
TRUE;
1899 *rowsign = (invflowrowsign |
INVERTED);
1900 *invertcommodity =
FALSE;
1917 unsigned char* nextrowsign,
1921 SCIP_Real* flowrowscores = mcfdata->flowrowscores;
1922 SCIP_Bool* plusflow = mcfdata->plusflow;
1923 SCIP_Bool* minusflow = mcfdata->minusflow;
1924 int* newcols = mcfdata->newcols;
1930 assert(nextrow !=
NULL);
1931 assert(nextrowsign !=
NULL);
1935 *nextinvertcommodity =
FALSE;
1940 assert(cols !=
NULL);
1943 while( mcfdata->nnewcols > 0 )
1949 unsigned char bestrowsign;
1956 c = newcols[mcfdata->nnewcols-1];
1957 mcfdata->nnewcols--;
1961 assert(plusflow[c] || minusflow[c]);
1962 if( plusflow[c] && minusflow[c] )
1968 bestinvertcommodity =
FALSE;
1973 for( i = 0; i < collen; i++ )
1976 unsigned char flowrowsign;
1982 getFlowrowFit(scip, mcfdata, row, k, &flowrowsign, &invertcommodity);
1985 if( flowrowsign != 0 )
1992 score = flowrowscores[r];
1993 assert(score > 0.0);
1999 if( (flowrowsign &
INVERTED) != 0 )
2002 if( score > bestscore )
2005 bestrowsign = flowrowsign;
2006 bestinvertcommodity = invertcommodity;
2016 if( bestrow !=
NULL )
2018 assert(bestscore > 0.0);
2019 assert(bestrowsign != 0);
2021 *nextrowsign = bestrowsign;
2022 *nextinvertcommodity = bestinvertcommodity;
2037 int* flowcands = mcfdata->flowcands;
2064 assert(failed !=
NULL);
2073 plusflow = mcfdata->plusflow;
2074 minusflow = mcfdata->minusflow;
2075 colcommodity = mcfdata->colcommodity;
2076 rowcommodity = mcfdata->rowcommodity;
2088 for( c = 0; c < ncols; c++ )
2089 colcommodity[c] = -1;
2090 for( r = 0; r < nrows; r++ )
2091 rowcommodity[r] = -1;
2093 assert(flowcands !=
NULL || mcfdata->nflowcands == 0);
2104 for( i = 0; i < mcfdata->nflowcands; i++ )
2107 unsigned char newrowsign;
2111 assert(flowcands !=
NULL);
2113 assert(0 <= r && r < nrows);
2117 getFlowrowFit(scip, mcfdata, newrow, mcfdata->ncommodities, &newrowsign, &newinvertcommodity);
2118 if( newrowsign == 0 )
2120 assert(!newinvertcommodity);
2121 assert((newrowsign &
INVERTED) == 0);
2124 SCIPdebugMessage(
" -------------------start new commodity %d--------------------- \n", mcfdata->ncommodities );
2133 if( newinvertcommodity )
2134 invertCommodity(scip, mcfdata, mcfdata->ncommodities-1, comrows, nnodes, comcolids, ncomcolids);
2139 comrows[
nnodes] = newrow;
2144 getNextFlowrow(scip, mcfdata, &newrow, &newrowsign, &newinvertcommodity);
2146 while( newrow !=
NULL );
2148 ncomnodes[mcfdata->ncommodities-1] =
nnodes;
2149 maxnnodes =
MAX(maxnnodes, nnodes);
2150 nflowvars += ncomcolids;
2151 SCIPdebugMessage(
" -> finished commodity %d: identified %d nodes, maxnnodes=%d\n", mcfdata->ncommodities-1, nnodes, maxnnodes);
2159 deleteCommodity(scip, mcfdata, mcfdata->ncommodities-1, comrows, nnodes, &ndelflowrows, &ndelflowvars);
2160 nflowrows -= ndelflowrows;
2161 nflowvars -= ndelflowvars;
2162 assert(nflowvars >= 0);
2163 assert(nflowrows >= 0);
2167 for( k = 0; k < mcfdata->ncommodities; k++ )
2179 for( i = 0; i < mcfdata->nflowcands; i++ )
2181 assert(flowcands !=
NULL);
2183 if( rowcommodity[r] == k )
2185 comrows[
nnodes] = rows[r];
2188 if( nnodes == ncomnodes[k] )
2193 assert(nnodes == ncomnodes[k]);
2194 deleteCommodity(scip, mcfdata, k, comrows, nnodes, &ndelflowrows, &ndelflowvars);
2195 nflowrows -= ndelflowrows;
2196 nflowvars -= ndelflowvars;
2197 assert(nflowvars >= 0);
2198 assert(nflowrows >= 0);
2207 MCFdebugMessage(
"identified %d commodities (%d empty) with a maximum of %d nodes and %d flowrows, %d flowvars \n",
2208 mcfdata->ncommodities, mcfdata->nemptycommodities, maxnnodes, nflowrows, nflowvars);
2210 assert(nflowvars >= 0);
2211 assert(nflowrows >= 0);
2230 unsigned char* capacityrowsigns = mcfdata->capacityrowsigns;
2233 unsigned char* flowrowsigns = mcfdata->capacityrowsigns;
2234 int* rowcommodity = mcfdata->rowcommodity;
2250 SCIP_Real* capacityrowscores = mcfdata->capacityrowscores;
2252 int *capacitycands = mcfdata->capacitycands;
2253 int ncapacitycands = mcfdata->ncapacitycands;
2255 assert(mcfdata->narcs == 0);
2256 assert(capacitycands !=
NULL || ncapacitycands == 0);
2265 colarcid = mcfdata->colarcid;
2266 rowarcid = mcfdata->rowarcid;
2269 for( c = 0; c < ncols; c++ )
2271 for( r = 0; r < nrows; r++ )
2275 for( i = 0; i < ncapacitycands; i++ )
2281 int nassignedflowvars;
2282 int nunassignedflowvars;
2285 assert(capacitycands !=
NULL);
2286 r = capacitycands[i];
2287 assert(0 <= r && r < nrows );
2288 capacityrow = rows[r];
2292 assert((capacityrowsigns[r] &
DISCARDED) == 0);
2293 assert(capacityrowscores[r] > 0.0);
2297 assert(rowarcid[r] == -1);
2300 assert( rowcommodity[r] == -1 );
2306 nassignedflowvars = 0;
2307 nunassignedflowvars = 0;
2308 for( k = 0; k < rowlen; k++ )
2311 assert(0 <= c && c < ncols);
2313 assert(-1 <= colcommodity[c] && colcommodity[c] < mcfdata->ncommodities);
2314 assert(-1 <= colarcid[c] && colarcid[c] < mcfdata->narcs);
2317 if( colcommodity[c] == -1 )
2321 if( colarcid[c] >= 0 )
2322 nassignedflowvars++;
2324 nunassignedflowvars++;
2331 if( nunassignedflowvars == 0 || nassignedflowvars >= nunassignedflowvars * 2 )
2333 SCIPdebugMessage(
"discarding capacity candidate row %d <%s> [score:%g]: %d assigned flowvars, %d unassigned flowvars\n",
2334 r,
SCIProwGetName(capacityrow), mcfdata->capacityrowscores[r], nassignedflowvars, nunassignedflowvars);
2340 assert(mcfdata->narcs <= mcfdata->capacityrowssize);
2341 if( mcfdata->narcs == mcfdata->capacityrowssize )
2343 mcfdata->capacityrowssize =
MAX(2*mcfdata->capacityrowssize, mcfdata->narcs+1);
2346 assert(mcfdata->narcs < mcfdata->capacityrowssize);
2347 assert(mcfdata->narcs < nrows);
2349 mcfdata->capacityrows[mcfdata->narcs] = capacityrow;
2352 assert(0 <= r && r < nrows);
2353 rowarcid[r] = mcfdata->narcs;
2364 SCIPdebugMessage(
"assigning capacity row %d <%s> with sign %+d to arc %d [score:%g]: %d assigned flowvars, %d unassigned flowvars\n",
2366 mcfdata->capacityrowscores[r], nassignedflowvars, nunassignedflowvars);
2369 for( k = 0; k < rowlen; k++ )
2372 assert(0 <= rowc && rowc < ncols);
2377 if( colcommodity[rowc] >= 0 && colarcid[rowc] == -1 )
2378 colarcid[rowc] = mcfdata->narcs;
2398 int* colarcid = mcfdata->colarcid;
2399 int* newcols = mcfdata->newcols;
2400 SCIP_ROW** capacityrows = mcfdata->capacityrows;
2401 SCIP_Bool* colisincident = mcfdata->colisincident;
2410 assert(!colisincident[i]);
2416 mcfdata->nnewcols = 0;
2418 for( i = 0; i < rowlen; i++ )
2431 arcid = colarcid[c];
2434 assert(arcid < mcfdata->
narcs);
2437 assert(capacityrows[arcid] !=
NULL);
2441 for( j = 0; j < capacityrowlen; j++ )
2449 if( colcommodity[caprowc] == -1 )
2451 assert(colarcid[caprowc] == -1);
2454 assert(colarcid[caprowc] <= arcid);
2457 if( colcommodity[caprowc] == basecommodity )
2461 if( !colisincident[caprowc] )
2463 assert(mcfdata->nnewcols < SCIPgetNLPCols(scip));
2464 colisincident[caprowc] =
TRUE;
2465 newcols[mcfdata->nnewcols] = caprowc;
2466 mcfdata->nnewcols++;
2480 int* basearcpattern,
2489 unsigned char* flowrowsigns = mcfdata->flowrowsigns;
2490 int* commoditysigns = mcfdata->commoditysigns;
2491 int narcs = mcfdata->narcs;
2492 int* rowcommodity = mcfdata->rowcommodity;
2493 int* colarcid = mcfdata->colarcid;
2494 int* arcpattern = mcfdata->zeroarcarray;
2507 int* overlappingarcs;
2508 int noverlappingarcs;
2513 *invertcommodity =
FALSE;
2516 for( i = 0; i <
narcs; i++ )
2517 assert(arcpattern[i] == 0);
2526 rowcom = rowcommodity[r];
2528 rowcomsign = commoditysigns[rowcom];
2529 assert(-1 <= rowcomsign && rowcomsign <= +1);
2534 incompatible =
FALSE;
2535 noverlappingarcs = 0;
2539 for( i = 0; i < rowlen; i++ )
2549 valsign = (rowvals[i] > 0.0 ? +1 : -1);
2552 if( (flowrowsigns[r] &
INVERTED) != 0 )
2555 arcid = colarcid[c];
2564 assert(arcid < narcs);
2567 if( basearcpattern[arcid] != 0 )
2574 if( ( valsign * basearcpattern[arcid] ) > 0 )
2579 if( rowcomsign == 0 )
2582 rowcomsign = validcomsign;
2584 else if( rowcomsign != validcomsign )
2587 incompatible =
TRUE;
2598 if( arcpattern[arcid] == 0 )
2600 overlappingarcs[noverlappingarcs] = arcid;
2603 arcpattern[arcid] += valsign;
2609 for( i = 0; i < noverlappingarcs; i++ )
2615 arcid = overlappingarcs[i];
2616 assert(0 <= arcid && arcid < narcs);
2619 basenum = ABS(basearcpattern[arcid]);
2620 arcnum = ABS(arcpattern[arcid]);
2621 assert(basenum != 0.0);
2622 assert(arcnum != 0.0);
2624 if( basenum > arcnum )
2625 overlap += arcnum/basenum;
2627 overlap += basenum/arcnum;
2629 arcpattern[arcid] = 0;
2633 if( !incompatible && overlap > 0.0 )
2636 int rowarcs = rowlen - nposuncap - nneguncap;
2637 int baserowarcs = baserowlen - basenposuncap - basenneguncap;
2640 assert(overlap <= (
SCIP_Real) baserowlen);
2641 assert(noverlappingarcs >= 1);
2643 *invertcommodity = (rowcomsign == -1);
2647 if( noverlappingarcs >= 2 )
2650 assert(rowarcs >= 0 && baserowarcs >= 0 );
2653 *score = overlap - (rowarcs + baserowarcs - 2.0 * overlap)/(2.0 * ncols + 1.0);
2655 *score = overlap - (rowarcs + baserowarcs - 4.0 * overlap)/(2.0 * ncols + 1.0);
2658 if(*invertcommodity)
2659 *score += 1.0 - (ABS(nneguncap - basenposuncap) + ABS(nposuncap - basenneguncap))/(2.0 * ncols + 1.0);
2661 *score += 1.0 - (ABS(nposuncap - basenposuncap) + ABS(nneguncap - basenneguncap))/(2.0 * ncols + 1.0);
2663 *score =
MAX(*score, 1e-6);
2667 SCIPdebugMessage(
" -> node similarity: row <%s>: incompatible=%u overlap=%g rowlen=%d baserowlen=%d score=%g\n",
2668 SCIProwGetName(row), incompatible, overlap, rowlen, baserowlen, *score);
2683 unsigned char* flowrowsigns = mcfdata->flowrowsigns;
2685 int* commoditysigns = mcfdata->commoditysigns;
2686 int narcs = mcfdata->narcs;
2687 int* flowcands = mcfdata->flowcands;
2688 int nflowcands = mcfdata->nflowcands;
2689 int* rowcommodity = mcfdata->rowcommodity;
2690 int* colarcid = mcfdata->colarcid;
2691 int* newcols = mcfdata->newcols;
2712 assert(mcfdata->nnodes == 0);
2724 rownodeid = mcfdata->rownodeid;
2725 colisincident = mcfdata->colisincident;
2735 for( r = 0; r < nrows; r++ )
2737 for( c = 0; c < ncols; c++ )
2738 colisincident[c] =
FALSE;
2740 assert(flowcands !=
NULL || nflowcands == 0);
2743 for( n = 0; n < nflowcands; n++ )
2752 assert(flowcands !=
NULL);
2754 assert(0 <= r && r < nrows);
2757 basecommodity = rowcommodity[r];
2758 if( basecommodity == -1 )
2761 assert(mcfdata->rowarcid[r] == -1);
2764 if( rownodeid[r] >= 0 )
2768 SCIPdebugMessage(
"assigning row %d <%s> of commodity %d to node %d [score: %g]\n",
2769 r,
SCIProwGetName(rows[r]), basecommodity, mcfdata->nnodes, mcfdata->flowrowscores[r]);
2770 rownodeid[r] = mcfdata->nnodes;
2778 if(ncommodities == 1)
2793 if( (flowrowsigns[r] &
INVERTED) != 0 )
2795 if( commoditysigns[basecommodity] == -1 )
2798 for( i = 0; i < rowlen; i++ )
2803 assert(0 <= c && c < ncols);
2804 arcid = colarcid[c];
2809 arcpattern[arcid]++;
2811 arcpattern[arcid]--;
2826 bestflowrows[i] =
NULL;
2827 bestscores[i] = 0.0;
2828 bestinverted[i] =
FALSE;
2840 for( i = 0; i < mcfdata->nnewcols; i++ )
2847 assert(0 <= c && c < ncols);
2848 assert(mcfdata->colcommodity[c] >= 0);
2849 assert(mcfdata->colcommodity[c] != basecommodity);
2852 assert(colisincident[c]);
2853 colisincident[c] =
FALSE;
2859 for( j = 0; j < collen; j++ )
2867 assert(0 <= colr && colr < nrows);
2870 if( rowprocessed[colr] )
2872 rowprocessed[colr] =
TRUE;
2875 rowcom = rowcommodity[colr];
2876 assert(rowcom != basecommodity);
2880 assert(rowcom == mcfdata->colcommodity[c]);
2881 assert((flowrowsigns[colr] & (
LHSASSIGNED | RHSASSIGNED)) != 0);
2882 assert(mcfdata->rowarcid[colr] == -1);
2885 if( rownodeid[colr] >= 0 )
2890 nposuncap, nneguncap, colrows[j], &score, &invertcommodity) );
2893 if( score > bestscores[rowcom] )
2895 bestflowrows[rowcom] = colrows[j];
2896 bestscores[rowcom] = score;
2897 bestinverted[rowcom] = invertcommodity;
2901 assert(bestflowrows[basecommodity] ==
NULL);
2908 if( bestflowrows[i] ==
NULL )
2912 assert(0 <= comr && comr < nrows);
2913 assert(rowcommodity[comr] == i);
2914 assert((flowrowsigns[comr] & (
LHSASSIGNED | RHSASSIGNED)) != 0);
2915 assert(rownodeid[comr] == -1);
2916 assert(mcfdata->nnodes >= 1);
2918 SCIPdebugMessage(
" -> assigning row %d <%s> of commodity %d to node %d [invert:%u]\n",
2919 comr,
SCIProwGetName(rows[comr]), i, mcfdata->nnodes-1, bestinverted[i]);
2920 rownodeid[comr] = mcfdata->nnodes-1;
2923 if( bestinverted[i] )
2925 assert(commoditysigns[i] != +1);
2926 commoditysigns[i] = -1;
2930 assert(commoditysigns[i] != -1);
2931 commoditysigns[i] = +1;
2954 int* commoditysigns = mcfdata->commoditysigns;
2957 for( k = 0; k < mcfdata->ncommodities; k++ )
2959 if( commoditysigns[k] == 0 )
2960 commoditysigns[k] = +1;
2975 unsigned char* flowrowsigns = mcfdata->flowrowsigns;
2976 int* commoditysigns = mcfdata->commoditysigns;
2977 int* rowcommodity = mcfdata->rowcommodity;
2978 int* rownodeid = mcfdata->rownodeid;
2979 int* colsources = mcfdata->colsources;
2980 int* coltargets = mcfdata->coltargets;
2988 assert(sourcenode !=
NULL);
2989 assert(targetnode !=
NULL);
2990 assert(colsources !=
NULL);
2991 assert(coltargets !=
NULL);
2997 if( colsources[c] >= -1 )
2999 assert(coltargets[c] >= -1);
3000 *sourcenode = colsources[c];
3001 *targetnode = coltargets[c];
3012 for( i = 0; i < collen; i++ )
3019 if( rownodeid[r] >= 0 )
3026 k = rowcommodity[r];
3027 assert(0 <= v && v < mcfdata->
nnodes);
3035 if( (flowrowsigns[r] &
INVERTED) != 0 )
3037 if( commoditysigns[k] == -1 )
3041 if( ( scale * colvals[i] ) > 0.0 )
3043 assert(*sourcenode == -1);
3045 if( *targetnode >= 0 )
3050 assert(*targetnode == -1);
3052 if( *sourcenode >= 0 )
3059 colsources[c] = *sourcenode;
3060 coltargets[c] = *targetnode;
3071 int* flowcands = mcfdata->flowcands;
3072 int nflowcands = mcfdata->nflowcands;
3074 unsigned char* flowrowsigns = mcfdata->flowrowsigns;
3076 int* rowcommodity = mcfdata->rowcommodity;
3078 int* rownodeid = mcfdata->rownodeid;
3079 int* colarcid = mcfdata->colarcid;
3080 int nnodes = mcfdata->nnodes;
3088 int* sortedflowcands;
3089 int* sortedflowcandnodeid;
3102 assert(mcfdata->nemptycommodities == 0);
3103 assert(ncommodities >= 0);
3107 if( ncommodities == 0 || nflowcands == 0 || nnodes == 0 )
3116 assert(rows !=
NULL);
3117 assert(cols !=
NULL || ncols == 0);
3128 for( n = 0; n < nflowcands; n++ )
3130 sortedflowcands[n] = flowcands[n];
3131 sortedflowcandnodeid[n] = rownodeid[flowcands[n]];
3135 SCIPsortIntInt(sortedflowcandnodeid, sortedflowcands, nflowcands);
3136 assert(sortedflowcandnodeid[0] <= 0);
3137 assert(sortedflowcandnodeid[nflowcands-1] == nnodes-1);
3140 for( v = 0; v <
nnodes; v++ )
3156 for( n = 0; n < nflowcands; n++ )
3158 if( sortedflowcandnodeid[n] >= 0 )
3160 assert(0 <= sortedflowcands[n] && sortedflowcands[n] <
SCIPgetNLPRows(scip));
3161 assert(rowcommodity[sortedflowcands[n]] == -1);
3163 assert(n < nflowcands);
3164 assert(sortedflowcandnodeid[n] == 0);
3169 for( v = 0; n < nflowcands; v++ )
3174 assert(0 <= sortedflowcands[n] && sortedflowcands[n] <
SCIPgetNLPRows(scip));
3175 assert(rowcommodity[sortedflowcands[n]] >= 0);
3176 assert(rownodeid[sortedflowcands[n]] == sortedflowcandnodeid[n]);
3177 assert(sortedflowcandnodeid[n] == v);
3178 assert(nadjnodes == 0);
3179 assert(ninccols == 0);
3184 for( ; n < nflowcands && sortedflowcandnodeid[n] == v; n++ )
3191 r = sortedflowcands[n];
3193 assert(mcfdata->rowarcid[r] == -1);
3198 for( i = 0; i < rowlen; i++ )
3209 arcid = colarcid[c];
3210 assert(-2 <= arcid && arcid < mcfdata->
narcs);
3211 assert(rowcommodity[r] == colcommodity[c]);
3221 else if( arcid == -1 )
3231 assert(-1 <= s && s < nnodes);
3232 assert(-1 <= t && t < nnodes);
3233 assert(s == v || t == v);
3244 if( s < 0 || t < 0 )
3252 assert(ninccols < ncols);
3253 inccols[ninccols] = c;
3269 if( sourcecount[u] + targetcount[u] == 1 )
3271 assert(nadjnodes < nnodes);
3272 adjnodes[nadjnodes] = u;
3280 for( l = 0; l < nadjnodes; l++ )
3285 assert(0 <= u && u < nnodes);
3286 assert(sourcecount[u] > 0 || targetcount[u] > 0);
3288 assert(ninccols >= 0);
3291 if( sourcecount[u] >= arcsthreshold )
3301 for( m = 0; m < ninccols; m++ )
3308 assert(0 <= c && c < ncols);
3310 assert(cols !=
NULL);
3312 assert(s == v || t == v);
3317 colarcid[c] = arcid;
3320 inccols[m] = inccols[ninccols-1];
3328 if( targetcount[u] >= arcsthreshold )
3338 for( m = 0; m < ninccols; m++ )
3345 assert(0 <= c && c < ncols);
3347 assert(cols !=
NULL);
3349 assert(s == v || t == v);
3353 assert(cols !=
NULL);
3355 colarcid[c] = arcid;
3358 inccols[m] = inccols[ninccols-1];
3367 for( l = 0; l < nadjnodes; l++ )
3375 for( l = 0; l < ninccols; l++ )
3377 assert(colarcid[inccols[l]] == -1);
3378 colarcid[inccols[l]] = -2;
3382 assert(n == nflowcands);
3383 assert(v == nnodes);
3387 for( n = 0; n < ncols; n++ )
3388 assert(colarcid[n] >= -1);
3399 MCFdebugMessage(
"network after finding uncapacitated arcs has %d nodes, %d arcs, and %d commodities\n",
3400 mcfdata->nnodes, mcfdata->narcs, mcfdata->ncommodities);
3412 int* flowcands = mcfdata->flowcands;
3413 int nflowcands = mcfdata->nflowcands;
3415 int* rowcommodity = mcfdata->rowcommodity;
3416 int* colarcid = mcfdata->colarcid;
3417 int* rowarcid = mcfdata->rowarcid;
3418 int* rownodeid = mcfdata->rownodeid;
3420 int* commoditysigns = mcfdata->commoditysigns;
3421 int narcs = mcfdata->narcs;
3422 int nnodes = mcfdata->nnodes;
3423 SCIP_ROW** capacityrows = mcfdata->capacityrows;
3435 int nnodesthreshold;
3436 int newncommodities;
3442 MCFdebugMessage(
"network before cleanup has %d nodes, %d arcs, and %d commodities\n", nnodes, narcs, ncommodities);
3450 permsize =
MAX(permsize, narcs);
3451 permsize =
MAX(permsize, nnodes);
3461 assert(flowcands !=
NULL || nflowcands == 0);
3464 for( i = 0; i < nflowcands; i++ )
3468 assert(flowcands !=
NULL);
3470 assert(0 <= r && r < nrows);
3471 assert((rownodeid[r] >= 0) == (rowcommodity[r] >= 0));
3472 if( rowcommodity[r] >= 0 )
3474 assert(rowcommodity[r] < ncommodities);
3475 nnodespercom[rowcommodity[r]]++;
3479 assert(capacityrows !=
NULL || narcs == 0);
3482 for( a = 0; a <
narcs; a++ )
3489 assert(capacityrows !=
NULL);
3491 assert(0 <= r && r < nrows);
3492 assert(rowarcid[r] == a);
3498 for( j = 0; j < rowlen; j++ )
3503 assert(0 <= c && c < ncols);
3504 if( colcommodity[c] >= 0 && colarcid[c] == a )
3506 assert(colcommodity[c] < ncommodities);
3507 arcisincom[colcommodity[c]] =
TRUE;
3522 maxnnodes =
MAX(maxnnodes, nnodespercom[k]);
3533 newncommodities = 0;
3536 SCIPdebugMessage(
" -> commodity %d: %d nodes, %d arcs\n", k, nnodespercom[k], narcspercom[k]);
3539 if( nnodespercom[k] >= nnodesthreshold && narcspercom[k] >= 1 )
3541 assert(newncommodities <= k);
3542 perm[k] = newncommodities;
3543 commoditysigns[newncommodities] = commoditysigns[k];
3550 if( newncommodities < ncommodities )
3559 SCIPdebugMessage(
" -> discarding %d of %d commodities\n", ncommodities - newncommodities, ncommodities);
3567 for( c = 0; c < ncols; c++ )
3569 if( colcommodity[c] >= 0 )
3571 assert(-1 <= colarcid[c] && colarcid[c] < narcs);
3572 assert(colcommodity[c] < mcfdata->ncommodities);
3573 colcommodity[c] = perm[colcommodity[c]];
3574 assert(colcommodity[c] < newncommodities);
3575 if( colcommodity[c] == -1 )
3580 else if( colarcid[c] >= 0 )
3581 arcisused[colarcid[c]] =
TRUE;
3584 for( i = 0; i < nflowcands; i++ )
3588 assert(flowcands !=
NULL);
3590 assert(0 <= r && r < nrows);
3591 assert((rownodeid[r] >= 0) == (rowcommodity[r] >= 0));
3592 if( rowcommodity[r] >= 0 )
3594 assert(0 <= rownodeid[r] && rownodeid[r] < nnodes);
3595 assert(rowcommodity[r] < mcfdata->ncommodities);
3596 rowcommodity[r] = perm[rowcommodity[r]];
3597 assert(rowcommodity[r] < newncommodities);
3598 if( rowcommodity[r] == -1 )
3604 nodeisused[rownodeid[r]] =
TRUE;
3608 mcfdata->ncommodities = newncommodities;
3609 ncommodities = newncommodities;
3613 for( a = 0; a <
narcs; a++ )
3617 assert(capacityrows !=
NULL);
3621 assert(newnarcs <= a);
3623 capacityrows[newnarcs] = capacityrows[a];
3632 assert(0 <= r && r < nrows);
3633 assert(rowarcid[r] == a);
3634 rowarcid[r] = perm[a];
3638 if( newnarcs < narcs )
3640 SCIPdebugMessage(
" -> discarding %d of %d arcs\n", narcs - newnarcs, narcs);
3642 for( c = 0; c < ncols; c++ )
3644 if( colarcid[c] >= 0 )
3646 colarcid[c] = perm[colarcid[c]];
3647 assert(colarcid[c] >= 0);
3650 mcfdata->narcs = newnarcs;
3654 for( a = 0; a <
narcs; a++ )
3657 assert(capacityrows !=
NULL);
3659 assert(0 <= r && r < nrows);
3660 assert(rowarcid[r] == a);
3666 for( v = 0; v <
nnodes; v++ )
3670 assert(newnnodes <= v);
3671 perm[v] = newnnodes;
3679 if( newnnodes < nnodes )
3681 SCIPdebugMessage(
" -> discarding %d of %d nodes\n", nnodes - newnnodes, nnodes);
3683 for( i = 0; i < nflowcands; i++ )
3687 assert(flowcands !=
NULL);
3689 assert(0 <= r && r < nrows);
3690 assert((rownodeid[r] >= 0) == (rowcommodity[r] >= 0));
3691 if( rowcommodity[r] >= 0 )
3693 assert(rowcommodity[r] < ncommodities);
3694 rownodeid[r] = perm[rownodeid[r]];
3695 assert(rownodeid[r] >= 0);
3698 mcfdata->nnodes = newnnodes;
3708 mcfdata->nemptycommodities = 0;
3716 MCFdebugMessage(
"network after cleanup has %d nodes, %d arcs, and %d commodities\n", nnodes, narcs, ncommodities);
3730 int* colarcid = mcfdata->colarcid;
3732 int narcs = mcfdata->narcs;
3733 int nnodes = mcfdata->nnodes;
3735 SCIP_ROW** capacityrows = mcfdata->capacityrows;
3737 SCIP_Real maxinconsistencyratio = sepadata->maxinconsistencyratio;
3738 SCIP_Real maxarcinconsistencyratio = sepadata->maxarcinconsistencyratio;
3750 int *flowvarspercom;
3763 assert(effortlevel !=
NULL);
3777 arcsources = mcfdata->arcsources;
3778 arctargets = mcfdata->arctargets;
3779 colsources = mcfdata->colsources;
3780 coltargets = mcfdata->coltargets;
3781 firstoutarcs = mcfdata->firstoutarcs;
3782 firstinarcs = mcfdata->firstinarcs;
3783 nextoutarcs = mcfdata->nextoutarcs;
3784 nextinarcs = mcfdata->nextinarcs;
3786 mcfdata->arcarraysize =
narcs;
3789 for( c = 0; c < ncols; c++ )
3796 for( v = 0; v <
nnodes; v++ )
3798 firstoutarcs[v] = -1;
3799 firstinarcs[v] = -1;
3801 for( a = 0; a <
narcs; a++ )
3803 nextoutarcs[a] = -1;
3817 mcfdata->ninconsistencies = 0.0;
3818 maxninconsistencies = maxinconsistencyratio * (
SCIP_Real)narcs;
3821 for( a = 0; a <
narcs; a++ )
3843 assert(mcfdata->rowarcid[r] == a);
3846 for( i = 0; i <
nnodes; i++ )
3848 assert(sourcenodecnt[i] == 0);
3849 assert(targetnodecnt[i] == 0);
3860 for( i = 0; i < rowlen; i++ )
3864 if( colarcid[c] >= 0 )
3866 int k = colcommodity[c];
3867 assert (0 <= k && k < ncommodities);
3868 flowvarspercom[k]++;
3869 if( !comtouched[k] )
3872 comtouched[k] =
TRUE;
3878 if( ntouchedcoms == 0 )
3880 capacityrows[a] =
NULL;
3888 totalsourcecnt = 0.0;
3889 totaltargetcnt = 0.0;
3891 for( i = 0; i < rowlen; i++ )
3895 if( colarcid[c] >= 0 )
3897 int k = colcommodity[c];
3902 assert (0 <= k && k < ncommodities);
3903 assert (comtouched[k]);
3904 assert (flowvarspercom[k] >= 1);
3910 weight = 1.0/flowvarspercom[k];
3913 if( sourcenodecnt[sourcev] == 0.0 && targetnodecnt[sourcev] == 0.0 )
3915 touchednodes[ntouchednodes] = sourcev;
3918 sourcenodecnt[sourcev] += weight;
3919 totalsourcecnt += weight;
3923 if( sourcenodecnt[targetv] == 0.0 && targetnodecnt[targetv] == 0.0 )
3925 touchednodes[ntouchednodes] = targetv;
3928 targetnodecnt[targetv] += weight;
3929 totaltargetcnt += weight;
3931 if( sourcev >= 0 || targetv >= 0 )
3932 totalnodecnt += weight;
3939 bestsourcecnt = 0.0;
3940 besttargetcnt = 0.0;
3941 for( i = 0; i < ntouchednodes; i++ )
3943 v = touchednodes[i];
3944 assert(0 <= v && v < nnodes);
3949 if( sourcenodecnt[v] >= targetnodecnt[v] )
3951 if( sourcenodecnt[v] > bestsourcecnt )
3954 bestsourcecnt = sourcenodecnt[v];
3959 if( targetnodecnt[v] > besttargetcnt )
3962 besttargetcnt = targetnodecnt[v];
3968 SCIP_Real nodecnt = sourcenodecnt[v] + targetnodecnt[v];
3972 if( nodecnt > bestsourcecnt )
3974 besttargetv = bestsourcev;
3975 besttargetcnt = bestsourcecnt;
3977 bestsourcecnt = nodecnt;
3979 else if( nodecnt > besttargetcnt )
3982 besttargetcnt = nodecnt;
3987 sourcenodecnt[v] = 0;
3988 targetnodecnt[v] = 0;
3994 totalsourcecnt = totalnodecnt;
3995 totaltargetcnt = totalnodecnt;
3997 assert(
SCIPisGE(scip,totalsourcecnt,bestsourcecnt));
3998 assert(
SCIPisGE(scip,totaltargetcnt,besttargetcnt));
3999 nsourceinconsistencies = (totalsourcecnt - bestsourcecnt)/ntouchedcoms;
4000 ntargetinconsistencies = (totaltargetcnt - besttargetcnt)/ntouchedcoms;
4003 if( nsourceinconsistencies > maxarcinconsistencyratio )
4009 if( ntargetinconsistencies > maxarcinconsistencyratio )
4016 assert(bestsourcev == -1 || bestsourcev != besttargetv);
4017 arcsources[a] = bestsourcev;
4018 arctargets[a] = besttargetv;
4019 SCIPdebugMessage(
"arc %d: %d -> %d (len=%d, sourcecnt=%g/%g, targetcnt=%g/%g, %g/%g inconsistencies)\n",
4020 a, bestsourcev, besttargetv, rowlen,
4021 bestsourcecnt, totalsourcecnt, besttargetcnt, totaltargetcnt,
4022 nsourceinconsistencies, ntargetinconsistencies);
4025 if( bestsourcev != -1 )
4027 nextoutarcs[a] = firstoutarcs[bestsourcev];
4028 firstoutarcs[bestsourcev] = a;
4030 if( besttargetv != -1 )
4032 nextinarcs[a] = firstinarcs[besttargetv];
4033 firstinarcs[besttargetv] = a;
4037 mcfdata->ninconsistencies += 0.5*(nsourceinconsistencies + ntargetinconsistencies);
4039 if( mcfdata->ninconsistencies > maxninconsistencies )
4041 MCFdebugMessage(
" -> reached maximal number of inconsistencies: %g > %g\n",
4042 mcfdata->ninconsistencies, maxninconsistencies);
4048 if( mcfdata->ninconsistencies <= maxninconsistencies && narcs > 0 && ncommodities > 0 )
4053 MCFdebugMessage(
"extracted network has %g inconsistencies (ratio %g) -> separating with effort %d\n",
4054 mcfdata->ninconsistencies, mcfdata->ninconsistencies/(
SCIP_Real)narcs, *effortlevel);
4085 int* firstoutarcs = mcfdata->firstoutarcs;
4086 int* firstinarcs = mcfdata->firstinarcs;
4087 int* nextoutarcs = mcfdata->nextoutarcs;
4088 int* nextinarcs = mcfdata->nextinarcs;
4089 int nnodes = mcfdata->nnodes;
4094 assert(nodevisited !=
NULL);
4095 assert(0 <= startv && startv < nnodes);
4096 assert(nodevisited[startv] ==
UNKNOWN);
4097 assert(compnodes !=
NULL);
4098 assert(ncompnodes !=
NULL);
4099 assert(comparcs !=
NULL);
4100 assert(ncomparcs !=
NULL);
4109 stacknodes[0] = startv;
4111 nodevisited[startv] =
ONSTACK;
4114 while( nstacknodes > 0 )
4119 assert(firstoutarcs !=
NULL);
4120 assert(firstinarcs !=
NULL);
4121 assert(nextoutarcs !=
NULL);
4122 assert(nextinarcs !=
NULL);
4125 v = stacknodes[nstacknodes-1];
4127 assert(0 <= v && v < nnodes);
4128 assert(nodevisited[v] ==
ONSTACK);
4132 assert(*ncompnodes < nnodes);
4133 compnodes[*ncompnodes] = v;
4137 for( a = firstoutarcs[v]; a != -1; a = nextoutarcs[a] )
4141 assert(0 <= a && a < mcfdata->
narcs);
4142 assert(arctargets !=
NULL);
4144 targetv = arctargets[a];
4147 if( targetv != -1 && nodevisited[targetv] ==
VISITED )
4151 assert(*ncomparcs < mcfdata->narcs);
4152 comparcs[*ncomparcs] = a;
4156 if( targetv != -1 && nodevisited[targetv] ==
UNKNOWN )
4158 assert(nstacknodes < nnodes);
4159 stacknodes[nstacknodes] = targetv;
4161 nodevisited[targetv] =
ONSTACK;
4166 for( a = firstinarcs[v]; a != -1; a = nextinarcs[a] )
4170 assert(0 <= a && a < mcfdata->
narcs);
4171 assert(arcsources !=
NULL);
4173 sourcev = arcsources[a];
4176 if( sourcev != -1 && nodevisited[sourcev] ==
VISITED )
4180 assert(*ncomparcs < mcfdata->narcs);
4181 comparcs[*ncomparcs] = a;
4185 if( sourcev != -1 && nodevisited[sourcev] ==
UNKNOWN )
4187 assert(nstacknodes < nnodes);
4188 stacknodes[nstacknodes] = sourcev;
4190 nodevisited[sourcev] =
ONSTACK;
4221 int mcfnetworkssize;
4223 assert(mcfnetworks !=
NULL);
4224 assert(nmcfnetworks !=
NULL);
4225 assert(effortlevel !=
NULL);
4229 *mcfnetworks =
NULL;
4231 mcfnetworkssize = 0;
4262 mcfdata.flowrowsigns =
NULL;
4263 mcfdata.flowrowscalars =
NULL;
4264 mcfdata.flowrowscores =
NULL;
4265 mcfdata.capacityrowsigns =
NULL;
4266 mcfdata.capacityrowscores =
NULL;
4267 mcfdata.flowcands =
NULL;
4268 mcfdata.nflowcands = 0;
4269 mcfdata.capacitycands =
NULL;
4270 mcfdata.ncapacitycands = 0;
4271 mcfdata.plusflow =
NULL;
4272 mcfdata.minusflow =
NULL;
4273 mcfdata.ncommodities = 0;
4274 mcfdata.nemptycommodities = 0;
4275 mcfdata.commoditysigns =
NULL;
4276 mcfdata.commoditysignssize = 0;
4277 mcfdata.colcommodity =
NULL;
4278 mcfdata.rowcommodity =
NULL;
4279 mcfdata.colarcid =
NULL;
4280 mcfdata.rowarcid =
NULL;
4281 mcfdata.rownodeid =
NULL;
4282 mcfdata.arcarraysize = 0;
4283 mcfdata.arcsources =
NULL;
4284 mcfdata.arctargets =
NULL;
4285 mcfdata.colsources =
NULL;
4286 mcfdata.coltargets =
NULL;
4287 mcfdata.firstoutarcs =
NULL;
4288 mcfdata.firstinarcs =
NULL;
4289 mcfdata.nextoutarcs =
NULL;
4290 mcfdata.nextinarcs =
NULL;
4291 mcfdata.newcols =
NULL;
4292 mcfdata.nnewcols = 0;
4295 mcfdata.ninconsistencies = 0.0;
4296 mcfdata.capacityrows =
NULL;
4297 mcfdata.capacityrowssize = 0;
4298 mcfdata.colisincident =
NULL;
4299 mcfdata.zeroarcarray =
NULL;
4306 assert(mcfdata.flowrowsigns !=
NULL);
4307 assert(mcfdata.flowrowscalars !=
NULL);
4308 assert(mcfdata.flowrowscores !=
NULL);
4309 assert(mcfdata.flowcands !=
NULL);
4311 if( mcfdata.nflowcands == 0 )
4318 assert(mcfdata.plusflow !=
NULL);
4319 assert(mcfdata.minusflow !=
NULL);
4320 assert(mcfdata.colcommodity !=
NULL);
4321 assert(mcfdata.rowcommodity !=
NULL);
4322 assert(mcfdata.newcols !=
NULL);
4328 printCommodities(scip, &mcfdata);
4335 assert(mcfdata.capacityrowsigns !=
NULL);
4336 assert(mcfdata.capacityrowscores !=
NULL);
4337 assert(mcfdata.capacitycands !=
NULL);
4339 if( mcfdata.ncapacitycands == 0 )
4347 assert(mcfdata.colarcid !=
NULL);
4348 assert(mcfdata.rowarcid !=
NULL);
4352 assert(mcfdata.rownodeid !=
NULL);
4353 assert(mcfdata.colisincident !=
NULL);
4354 assert(mcfdata.zeroarcarray !=
NULL);
4365 assert(mcfdata.arcsources !=
NULL);
4366 assert(mcfdata.arctargets !=
NULL);
4367 assert(mcfdata.colsources !=
NULL);
4368 assert(mcfdata.coltargets !=
NULL);
4369 assert(mcfdata.firstoutarcs !=
NULL);
4370 assert(mcfdata.firstinarcs !=
NULL);
4371 assert(mcfdata.nextoutarcs !=
NULL);
4372 assert(mcfdata.nextinarcs !=
NULL);
4388 printCommodities(scip, &mcfdata);
4401 for( v = 0; v < mcfdata.nnodes; v++ )
4405 for( v = 0; v < mcfdata.nnodes; v++ )
4412 if( nodevisited[v] ==
VISITED )
4417 assert(ncompnodes >= 1);
4418 assert(compnodes[0] == v);
4419 assert(nodevisited[v] ==
VISITED);
4422 if( ncompnodes >= minnodes && ncomparcs >=
MINARCS )
4429 assert(*nmcfnetworks <= mcfnetworkssize);
4430 if( *nmcfnetworks == mcfnetworkssize )
4432 mcfnetworkssize =
MAX(2*mcfnetworkssize, *nmcfnetworks+1);
4435 assert(*nmcfnetworks < mcfnetworkssize);
4441 SCIP_CALL(
mcfnetworkFill(scip, mcfnetwork, &mcfdata, compnodeid, compnodes, ncompnodes, comparcs, ncomparcs) );
4444 for( i = *nmcfnetworks; i > 0 && mcfnetwork->
nnodes > (*mcfnetworks)[i-1]->nnodes; i-- )
4445 (*mcfnetworks)[i] = (*mcfnetworks)[i-1];
4446 (*mcfnetworks)[i] = mcfnetwork;
4451 minnodes =
MAX(minnodes, (*mcfnetworks)[*nmcfnetworks-1]->
nnodes);
4456 SCIPdebugMessage(
" -> discarded network with %d nodes and %d arcs due to maxnetworks (minnodes=%d)\n",
4457 (*mcfnetworks)[*nmcfnetworks-1]->
nnodes, (*mcfnetworks)[*nmcfnetworks-1]->
narcs, minnodes);
4465 SCIPdebugMessage(
" -> discarded component with %d nodes and %d arcs\n", ncompnodes, ncomparcs);
4508 #ifdef COUNTNETWORKVARIABLETYPES 4530 int nintflowvars = 0;
4531 int nbinflowvars = 0;
4532 int ncontflowvars = 0;
4534 int nintcapvars = 0;
4535 int nbincapvars = 0;
4536 int ncontcapvars = 0;
4543 for(c=0; c < ncols; c++)
4544 colvisited[c]=
FALSE;
4549 for(m=0; m < nmcfnetworks; m++)
4561 for(c=0; c < ncols; c++)
4565 if(colcommodity[c] >= 0 && ! colvisited[c])
4570 colvisited[c] =
TRUE;
4593 for( a = 0; a <
narcs; a++ )
4596 row = arccapacityrows[a];
4608 for( i = 0; i < rowlen; i++ )
4613 if(colcommodity[c] == -1 && ! colvisited[c] )
4616 colvisited[c] =
TRUE;
4643 for( v = 0; v <
nnodes; v++ )
4646 row = nodeflowrows[v][k];
4656 MCFdebugMessage(
" nof flowvars: %5d of which [ %d , %d , %d ] are continuous, integer, binary\n",
4657 nflowvars, ncontflowvars, nintflowvars, nbinflowvars);
4658 MCFdebugMessage(
" nof capvars: %5d of which [ %d , %d , %d ] are continuous, integer, binary\n",
4659 ncapvars, ncontcapvars, nintcapvars, nbincapvars);
4679 int* representatives,
4686 for( v = 0; v < nelems; v++ )
4687 representatives[v] = v;
4693 int* representatives,
4697 assert(representatives !=
NULL);
4699 while( v != representatives[v] )
4701 representatives[v] = representatives[representatives[v]];
4702 v = representatives[v];
4711 int* representatives,
4716 assert(rep1 != rep2);
4717 assert(representatives[rep1] == rep1);
4718 assert(representatives[rep2] == rep2);
4724 representatives[rep2] = rep1;
4726 representatives[rep1] = rep2;
4742 if( nodepair1->weight > nodepair2->weight )
4744 else if( nodepair1->weight < nodepair2->weight )
4779 assert(mcfnetwork !=
NULL);
4785 assert(nodepair1 !=
NULL);
4786 assert(nodepair2 !=
NULL);
4788 source1 = nodepair1->node1;
4789 source2 = nodepair2->node1;
4790 target1 = nodepair1->node2;
4791 target2 = nodepair2->node2;
4793 assert(source1 >=0 && source1 < mcfnetwork->
nnodes);
4794 assert(source2 >=0 && source2 < mcfnetwork->nnodes);
4795 assert(target1 >=0 && target1 < mcfnetwork->nnodes);
4796 assert(target2 >=0 && target2 < mcfnetwork->nnodes);
4797 assert(source1 <= target1);
4798 assert(source2 <= target2);
4800 return (source1 == source2 && target1 == target2);
4814 unsigned int hashval;
4818 assert(mcfnetwork !=
NULL);
4822 assert( nodepair !=
NULL);
4824 source = nodepair->node1;
4825 target = nodepair->node2;
4827 assert(source >=0 && source < mcfnetwork->
nnodes);
4828 assert(target >=0 && target < mcfnetwork->nnodes);
4829 assert(source <= target);
4831 hashval = (source << 16) + target;
4854 #ifdef BETTERWEIGHTFORDEMANDNODES 4875 assert(mcfnetwork !=
NULL);
4877 #ifdef BETTERWEIGHTFORDEMANDNODES 4887 assert(nodepairqueue !=
NULL);
4897 hashGetKeyNodepairs, hashKeyEqNodepairs, hashKeyValNodepairs, (
void*) mcfnetwork) );
4904 for( a = 0; a < mcfnetwork->
narcs; a++ )
4926 assert(nodepair.node1 < mcfnetwork->
nnodes);
4927 assert(nodepair.node2 < mcfnetwork->
nnodes);
4928 if( nodepair.node1 == -1 || nodepair.node2 == -1 )
4932 if( capacityrow !=
NULL )
4948 slack =
MAX(slack, 0.0);
4952 assert(scale > 0.0);
4962 for( i = 0; i < rowlen; i++ )
4969 if(colcommodity[c] >= 0)
4981 SCIPdebugMessage(
"cap arc -- slack:%g -- dual:%g -- flow:%g -- cap:%g \n", scale * slack, dualsol/scale, totalflow * scale, totalcap * scale);
4983 SCIPdebugMessage(
"cap arc -- slack:%g -- dual:%g1\n", scale * slack, dualsol/scale);
4987 nodepair.weight = scale * slack - ABS(dualsol)/scale;
4988 #ifdef USEFLOWFORTIEBREAKING 4991 nodepair.weight += totalflow * scale;
4992 nodepair.weight =
MIN( nodepair.weight, -0.0001);
4995 #ifdef USECAPACITYFORTIEBREAKING 4998 nodepair.weight += totalcap * scale;
4999 nodepair.weight =
MIN( nodepair.weight, -0.0001);
5015 if( nodepairptr !=
NULL )
5018 SCIPdebugMessage(
"nodepair known [%d,%d] -- old weight:%g -- new weight:%g\n", nodepair.node1,nodepair.node2,nodepairptr->weight,
5019 MIN(nodepair.weight, nodepairptr->weight));
5020 nodepairptr->weight =
MIN(nodepair.weight, nodepairptr->weight);
5025 nodepairs = (*nodepairqueue)->nodepairs;
5027 assert(nnodepairs < mcfnetwork->
narcs);
5028 nodepairs[nnodepairs] = nodepair;
5031 SCIPdebugMessage(
"new nodepair [%d,%d]-- weight:%g\n", nodepair.node1, nodepair.node2, nodepair.weight);
5042 #ifdef BETTERWEIGHTFORDEMANDNODES 5050 nodepairs = (*nodepairqueue)->nodepairs;
5051 for( n = 0; n < nnodepairs; n++ )
5055 maxweight =
MAX(maxweight, nodepairs[n].weight);
5057 minweight =
MIN(minweight, nodepairs[n].weight);
5067 for( n = 0; n < nnodepairs; n++ )
5069 int node1 = nodepairs[n].node1;
5070 int node2 = nodepairs[n].node2;
5072 #ifdef BETTERWEIGHTFORDEMANDNODES 5079 SCIPdebugMessage(
"nodepair [%d,%d] weight %g\n", node1,node2,nodepairs[n].weight);
5087 if( nodeflowrows[node1][k] ==
NULL )
5090 if( nodeflowscales[node1][k] > 0.0 )
5107 if( nodeflowrows[node2][k] ==
NULL )
5110 if( nodeflowscales[node2][k] > 0.0 )
5132 if( !hasdemand1 || !hasdemand2 )
5133 nodepairs[n].weight += maxweight;
5139 if( hasdemand1 && hasdemand2)
5140 nodepairs[n].weight += minweight;
5143 SCIPdebugMessage(
"nodepair [%d,%d] weight %g\n", node1,node2,nodepairs[n].weight);
5160 assert(nodepairqueue !=
NULL);
5161 assert(*nodepairqueue !=
NULL);
5175 assert(nodepairqueue !=
NULL);
5188 assert(nodepairqueue !=
NULL);
5236 assert(mcfnetwork !=
NULL);
5237 assert(nodepartition !=
NULL);
5238 assert(mcfnetwork->
nnodes >= 1);
5246 (*nodepartition)->nclusters = 0;
5255 nclustersleft = mcfnetwork->
nnodes;
5267 assert(nodepair !=
NULL);
5268 node1 = nodepair->node1;
5269 node2 = nodepair->node2;
5270 weight = nodepair->weight;
5272 assert(node1 >= 0 && node1 < mcfnetwork->
nnodes);
5273 assert(node2 >= 0 && node2 < mcfnetwork->nnodes);
5278 assert(0 <= node1rep && node1rep < mcfnetwork->nnodes);
5279 assert(0 <= node2rep && node2rep < mcfnetwork->nnodes);
5282 if( node1rep == node2rep )
5286 SCIPdebugMessage(
"shrinking nodepair (%d,%d) with weight %g: join representatives %d and %d\n",
5287 node1, node2, weight, node1rep, node2rep);
5293 assert((*nodepartition)->representatives[0] == 0);
5298 if( nclustersleft > nclusters )
5300 for( v = 1; v < mcfnetwork->
nnodes && nclustersleft > nclusters; v++ )
5312 assert(nclustersleft <= nclusters);
5317 for( v = 0; v < mcfnetwork->
nnodes; v++ )
5327 c = (*nodepartition)->nclusters;
5328 (*nodepartition)->nclusters++;
5331 c = (*nodepartition)->nodeclusters[rep];
5332 assert(0 <= c && c < nclusters);
5335 (*nodepartition)->nodeclusters[v] = c;
5341 for( c = 0; c < (*nodepartition)->nclusters; c++ )
5343 (*nodepartition)->clusterbegin[c] = pos;
5344 pos += clustersize[c];
5346 assert(pos == mcfnetwork->
nnodes);
5347 (*nodepartition)->clusterbegin[(*nodepartition)->nclusters] = mcfnetwork->
nnodes;
5351 for( v = 0; v < mcfnetwork->
nnodes; v++ )
5353 c = (*nodepartition)->nodeclusters[v];
5354 assert(0 <= c && c < (*nodepartition)->nclusters);
5355 pos = (*nodepartition)->clusterbegin[c] + clustersize[c];
5356 assert(pos < (*nodepartition)->clusterbegin[c+1]);
5357 (*nodepartition)->clusternodes[pos] = v;
5377 assert(nodepartition !=
NULL);
5378 assert(*nodepartition !=
NULL);
5391 unsigned int partition,
5402 if( nodepartition ==
NULL )
5403 return ((v == (
int)partition) == !inverted);
5407 unsigned int clusterbit;
5409 cluster = nodepartition->nodeclusters[v];
5410 assert(0 <= cluster && cluster < nodepartition->nclusters);
5411 clusterbit = (1 << cluster);
5413 return (((partition & clusterbit) != 0) == !inverted);
5423 unsigned int partition
5426 const int* nodeclusters = nodepartition->nodeclusters;
5436 assert(nodepartition !=
NULL);
5437 nclusters = nodepartition->nclusters;
5444 ncomponents = nclusters;
5445 assert(ncomponents >= 2);
5448 for( a = 0; a <
narcs; a++ )
5450 int s = arcsources[a];
5451 int t = arctargets[a];
5454 if( s == -1 || t == -1 )
5465 assert(0 <= s && s < mcfnetwork->
nnodes);
5466 assert(0 <= t && t < mcfnetwork->nnodes);
5469 cs = nodeclusters[s];
5470 ct = nodeclusters[t];
5471 assert(0 <= cs && cs < nclusters);
5472 assert(0 <= ct && ct < nclusters);
5481 if( repcs == repct )
5488 if( ncomponents <= 2 )
5498 assert(ncomponents >= 2);
5500 return (ncomponents == 2);
5505 void nodepartitionPrint(
5511 for( c = 0; c < nodepartition->nclusters; c++ )
5516 for( i = nodepartition->clusterbegin[c]; i < nodepartition->clusterbegin[c+1]; i++ )
5531 unsigned int partition
5540 if( nodepartition ==
NULL )
5545 file = fopen(filename,
"w");
5553 fprintf(file,
"graph\n");
5554 fprintf(file,
"[\n");
5555 fprintf(file,
" hierarchic 1\n");
5556 fprintf(file,
" label \"\"\n");
5557 fprintf(file,
" directed 1\n");
5560 for( v = 0; v < mcfnetwork->
nnodes; v++ )
5571 fprintf(file,
" node\n");
5572 fprintf(file,
" [\n");
5573 fprintf(file,
" id %d\n", v);
5574 fprintf(file,
" label \"%s\"\n", label);
5575 fprintf(file,
" graphics\n");
5576 fprintf(file,
" [\n");
5577 fprintf(file,
" w 30.0\n");
5578 fprintf(file,
" h 30.0\n");
5579 fprintf(file,
" type \"ellipse\"\n");
5581 fprintf(file,
" fill \"#FF0000\"\n");
5583 fprintf(file,
" fill \"#00FF00\"\n");
5584 fprintf(file,
" outline \"#000000\"\n");
5585 fprintf(file,
" ]\n");
5586 fprintf(file,
" LabelGraphics\n");
5587 fprintf(file,
" [\n");
5588 fprintf(file,
" text \"%s\"\n", label);
5589 fprintf(file,
" fontSize 13\n");
5590 fprintf(file,
" fontName \"Dialog\"\n");
5591 fprintf(file,
" anchor \"c\"\n");
5592 fprintf(file,
" ]\n");
5594 fprintf(file,
" gid %d\n", mcfnetwork->
nnodes+1);
5596 fprintf(file,
" gid %d\n", mcfnetwork->
nnodes+2);
5597 fprintf(file,
" ]\n");
5601 fprintf(file,
" node\n");
5602 fprintf(file,
" [\n");
5603 fprintf(file,
" id %d\n", mcfnetwork->
nnodes);
5604 fprintf(file,
" label \"?\"\n");
5605 fprintf(file,
" graphics\n");
5606 fprintf(file,
" [\n");
5607 fprintf(file,
" w 30.0\n");
5608 fprintf(file,
" h 30.0\n");
5609 fprintf(file,
" type \"ellipse\"\n");
5610 fprintf(file,
" fill \"#FFFFFF\"\n");
5611 fprintf(file,
" outline \"#000000\"\n");
5612 fprintf(file,
" ]\n");
5613 fprintf(file,
" LabelGraphics\n");
5614 fprintf(file,
" [\n");
5615 fprintf(file,
" text \"?\"\n");
5616 fprintf(file,
" fontSize 13\n");
5617 fprintf(file,
" fontName \"Dialog\"\n");
5618 fprintf(file,
" anchor \"c\"\n");
5619 fprintf(file,
" ]\n");
5620 fprintf(file,
" ]\n");
5623 fprintf(file,
" node\n");
5624 fprintf(file,
" [\n");
5625 fprintf(file,
" id %d\n", mcfnetwork->
nnodes+1);
5626 fprintf(file,
" label \"Partition S\"\n");
5627 fprintf(file,
" graphics\n");
5628 fprintf(file,
" [\n");
5629 fprintf(file,
" type \"roundrectangle\"\n");
5630 fprintf(file,
" fill \"#CAECFF84\"\n");
5631 fprintf(file,
" outline \"#666699\"\n");
5632 fprintf(file,
" outlineStyle \"dotted\"\n");
5633 fprintf(file,
" topBorderInset 0\n");
5634 fprintf(file,
" bottomBorderInset 0\n");
5635 fprintf(file,
" leftBorderInset 0\n");
5636 fprintf(file,
" rightBorderInset 0\n");
5637 fprintf(file,
" ]\n");
5638 fprintf(file,
" LabelGraphics\n");
5639 fprintf(file,
" [\n");
5640 fprintf(file,
" text \"Partition S\"\n");
5641 fprintf(file,
" fill \"#99CCFF\"\n");
5642 fprintf(file,
" fontSize 15\n");
5643 fprintf(file,
" fontName \"Dialog\"\n");
5644 fprintf(file,
" alignment \"right\"\n");
5645 fprintf(file,
" autoSizePolicy \"node_width\"\n");
5646 fprintf(file,
" anchor \"t\"\n");
5647 fprintf(file,
" borderDistance 0.0\n");
5648 fprintf(file,
" ]\n");
5649 fprintf(file,
" isGroup 1\n");
5650 fprintf(file,
" ]\n");
5653 fprintf(file,
" node\n");
5654 fprintf(file,
" [\n");
5655 fprintf(file,
" id %d\n", mcfnetwork->
nnodes+2);
5656 fprintf(file,
" label \"Partition T\"\n");
5657 fprintf(file,
" graphics\n");
5658 fprintf(file,
" [\n");
5659 fprintf(file,
" type \"roundrectangle\"\n");
5660 fprintf(file,
" fill \"#CAECFF84\"\n");
5661 fprintf(file,
" outline \"#666699\"\n");
5662 fprintf(file,
" outlineStyle \"dotted\"\n");
5663 fprintf(file,
" topBorderInset 0\n");
5664 fprintf(file,
" bottomBorderInset 0\n");
5665 fprintf(file,
" leftBorderInset 0\n");
5666 fprintf(file,
" rightBorderInset 0\n");
5667 fprintf(file,
" ]\n");
5668 fprintf(file,
" LabelGraphics\n");
5669 fprintf(file,
" [\n");
5670 fprintf(file,
" text \"Partition T\"\n");
5671 fprintf(file,
" fill \"#99CCFF\"\n");
5672 fprintf(file,
" fontSize 15\n");
5673 fprintf(file,
" fontName \"Dialog\"\n");
5674 fprintf(file,
" alignment \"right\"\n");
5675 fprintf(file,
" autoSizePolicy \"node_width\"\n");
5676 fprintf(file,
" anchor \"t\"\n");
5677 fprintf(file,
" borderDistance 0.0\n");
5678 fprintf(file,
" ]\n");
5679 fprintf(file,
" isGroup 1\n");
5680 fprintf(file,
" ]\n");
5683 for( a = 0; a < mcfnetwork->
narcs; a++ )
5695 hasfractional =
FALSE;
5706 for( i = 0; i < rowlen; i++ )
5713 hasfractional =
TRUE;
5721 fprintf(file,
" edge\n");
5722 fprintf(file,
" [\n");
5725 fprintf(file,
" label \"%s\"\n", label);
5726 fprintf(file,
" graphics\n");
5727 fprintf(file,
" [\n");
5729 fprintf(file,
" fill \"#000000\"\n");
5731 fprintf(file,
" fill \"#FF0000\"\n");
5733 fprintf(file,
" style \"dashed\"\n");
5734 fprintf(file,
" width 1\n");
5735 fprintf(file,
" targetArrow \"standard\"\n");
5736 fprintf(file,
" ]\n");
5737 fprintf(file,
" LabelGraphics\n");
5738 fprintf(file,
" [\n");
5739 fprintf(file,
" text \"%s\"\n", label);
5740 fprintf(file,
" ]\n");
5741 fprintf(file,
" ]\n");
5745 fprintf(file,
"]\n");
5780 assert(scip !=
NULL);
5781 assert(sepadata !=
NULL);
5782 assert(cutcoefs !=
NULL);
5783 assert(ncuts !=
NULL);
5784 assert(cutoff !=
NULL);
5788 assert(nvars == 0 || vars !=
NULL);
5793 if( sepadata->separateknapsack )
5803 cutislocal,
FALSE, sepadata->dynamiccuts) );
5807 for( v = 0; v < nvars; v++ )
5814 if( sepadata->separateknapsack )
5816 assert(cutvars !=
NULL && cutvals !=
NULL);
5817 cutvars[ncutvars] = vars[v];
5818 cutvals[ncutvars] = cutcoefs[v];
5831 SCIPdebugMessage(
" -> found MCF cut <%s>: rhs=%f, act=%f eff=%f rank=%d\n",
5836 if( !(*cutoff) && !cutislocal )
5846 if( !(*cutoff) && sepadata->separateknapsack)
5849 SCIP_CALL(
SCIPseparateRelaxedKnapsack(scip,
NULL, sepa, ncutvars, cutvars, cutvals, +1.0, cutrhs, sol, cutoff, ncuts) );
5899 unsigned int partition;
5900 unsigned int allpartitions;
5901 unsigned int startpartition;
5915 maxsepacuts = sepadata->maxsepacutsroot;
5917 maxsepacuts = sepadata->maxsepacuts;
5918 if( maxsepacuts < 0 )
5919 maxsepacuts = INT_MAX;
5924 maxtestdelta = sepadata->maxtestdelta;
5925 if( maxtestdelta <= 0 )
5926 maxtestdelta = INT_MAX;
5959 if( nodepartition ==
NULL )
5963 allpartitions = (
unsigned int) nnodes;
5964 SCIPdebugMessage(
"maxtestdelta: %d, maxsepacuts: %d, nnodes: %d \n", maxtestdelta, maxsepacuts, nnodes);
5971 int nclusters = nodepartition->nclusters;
5973 assert((
unsigned int)nclusters <= 8*
sizeof(
unsigned int));
5974 SCIPdebugMessage(
"maxtestdelta: %d, maxsepacuts: %d, nclusters: %d \n", maxtestdelta, maxsepacuts, nclusters);
5981 allpartitions = (1 << (nclusters-1));
5985 for( partition = startpartition; partition <= allpartitions-1 && !
SCIPisStopped(scip) && *ncuts < maxsepacuts && !*cutoff; partition++ )
5999 if( sepadata->checkcutshoreconnectivity )
6006 SCIPdebugMessage(
"generating cluster cuts for partition 0x%x \n", partition );
6007 SCIPdebugMessage(
" -> either shore S or shore T is not connected - skip partition.\n");
6012 for( inverted =
FALSE; inverted <= useinverted && !*cutoff; inverted++ )
6015 if( nodepartition ==
NULL )
6017 SCIPdebugMessage(
"generating single-node cuts for node %u (inverted: %u)\n", partition, inverted);
6021 SCIPdebugMessage(
"generating cluster cuts for partition 0x%x (inverted: %u)\n", partition, inverted);
6025 SCIP_CALL( outputGraph(scip, mcfnetwork, nodepartition, inverted, partition) );
6043 for( v = 0; v <
nnodes; v++ )
6057 if( nodeflowrows[v][k] ==
NULL )
6060 if( nodeflowscales[v][k] > 0.0 )
6064 if( nodeflowinverted[v][k] )
6067 comcutdemands[k] += rhs * nodeflowscales[v][k];
6070 assert (1 <= nnodesinS && nnodesinS <= nnodes-1);
6075 if( sepadata->separatesinglenodecuts && nodepartition !=
NULL && (nnodesinS == 1 || nnodesinS == nnodes-1) )
6077 SCIPdebugMessage(
" -> shore S or T has only one node - skip partition.\n");
6087 SCIPdebugMessage(
" -> commodity %d: directed cutdemand=%g\n", k, comcutdemands[k]);
6097 SCIPdebugMessage(
" -> commodity %d: undirected cutdemand=%g\n", k, comcutdemands[k]);
6102 if( k == ncommodities )
6106 for( a = 0; a <
narcs; a++ )
6115 assert(arcsources[a] < nnodes);
6116 assert(arctargets[a] < nnodes);
6122 if(
nodeInPartition(nodepartition, partition, inverted, arcsources[a]) ||
6132 if(
nodeInPartition(nodepartition, partition, inverted, arcsources[a]) &&
6138 if( !
nodeInPartition(nodepartition, partition, inverted, arcsources[a]) &&
6147 if( arccapacityrows[a] ==
NULL )
6155 assert(rowweights[r] == 0.0);
6161 if( arcsources[a] == -1 || arctargets[a] == -1 )
6171 assert(maxcoef > 0.0);
6176 rowweights[r] = arccapacityscales[a];
6181 if( sepadata->separateflowcutset )
6183 if( rowweights[r] > 0.0 )
6193 for( j = 0; j < rowlen; j++ )
6198 coef = rowvals[j] * arccapacityscales[a];
6204 k = colcommodity[c];
6206 comdemands[k] = coef;
6220 while( left <= right )
6222 int mid = (left+right)/2;
6224 if(
REALABS( deltas[mid] / coef - 1.0 ) < 1e-03 )
6229 else if( coef < deltas[mid] )
6238 assert(right == left-1);
6239 assert(ndeltas <= deltassize);
6240 if( ndeltas == deltassize )
6245 if( left < ndeltas )
6247 for( d = ndeltas; d > left; d-- )
6248 deltas[d] = deltas[d-1];
6250 deltas[left] = coef;
6259 for( v = 0; v <
nnodes; v++ )
6268 if( comdemands[k] == 0.0 )
6271 scale = comdemands[k];
6294 if( comcutdemands[k] > 0.0 )
6313 if( nodeflowrows[v][k] ==
NULL )
6322 assert(rowweights[r] == 0.0);
6328 rowweights[r] = scale * nodeflowscales[v][k];
6329 if( nodeflowinverted[v][k] )
6330 rowweights[r] *= -1.0;
6331 SCIPdebugMessage(
" -> node %d, commodity %d, r=%d, flow row <%s>: scale=%g weight=%g slack=%g dual=%g\n",
6332 v, k, r,
SCIProwGetName(nodeflowrows[v][k]), scale, rowweights[r],
6335 if( sepadata->separateflowcutset )
6337 if( nodeflowscales[v][k] > 0.0 )
6353 if( sepadata->separateflowcutset )
6356 bestdelta = deltas[ndeltas-1];
6362 for( d = ndeltas-1; d >= 0 && d >= ndeltas-maxtestdelta; d-- )
6381 NULL, 1.0/deltas[d],
NULL,
NULL, cutcoefs, &cutrhs, &cutact, &success, &cutislocal, &cutrank) );
6390 if( sepadata->separateflowcutset )
6393 relviolation = (cutact - cutrhs) /
MAX( abscutrhs , 1.0 );
6394 if( relviolation > bestrelviolation )
6396 bestdelta = deltas[d];
6397 bestrelviolation = relviolation;
6403 SCIPdebugMessage(
"success -> delta = %g -> rhs: %g, act: %g\n", deltas[d], cutrhs, cutact);
6404 SCIP_CALL(
addCut(scip, sepa, sepadata, sol, cutcoefs, cutrhs, cutislocal, cutrank, ncuts, cutoff) );
6409 for( a = 0; a <
narcs; a++ )
6411 if( arccapacityrows[a] !=
NULL )
6417 if( r >= 0 && rowweights[r] != 0.0 )
6419 MCFdebugMessage(
" -> arc %d, capacity row <%s>: weight=%g slack=%g prod=%g dual=%g\n", a,
6431 if( sepadata->separateflowcutset && oldncuts == *ncuts && !*cutoff )
6434 f0 =
SCIPfrac(scip, baserhs/bestdelta);
6439 totalviolationdelta = 0.0;
6440 onedivoneminsf0 = 1.0/(1.0 - f0);
6441 for( a = 0; a <
narcs; a++ )
6455 if( arccapacityrows[a] ==
NULL )
6466 if( rowweights[r] == 0.0 )
6481 rowweight = rowweights[r]/bestdelta;
6486 violationdelta = rowweight * (rowlhs - rowconstant);
6488 violationdelta = rowweight * (rowrhs - rowconstant);
6490 for( j = 0; j < rowlen; j++ )
6498 coef = rowvals[j] * rowweight;
6509 if( colcommodity[c] >= 0 )
6520 mircoef =
SCIPfloor(scip, coef) + (fj - f0)*onedivoneminsf0;
6527 mircoef = coef * onedivoneminsf0;
6532 if( colcommodity[c] >= 0 )
6533 violationdelta += mircoef * solval;
6535 violationdelta -= mircoef * solval;
6540 SCIPdebugMessage(
" -> discarding capacity row <%s> of weight %g and slack %g: increases MIR violation by %g\n",
6543 rowweights[r] = 0.0;
6544 totalviolationdelta += violationdelta;
6549 if( totalviolationdelta > 0.0 )
6562 SCIPdebugMessage(
"applying MIR with delta = %g to flowcut inequality (violation improvement: %g)\n", bestdelta, totalviolationdelta);
6565 NULL, 1.0/bestdelta,
NULL,
NULL, cutcoefs, &cutrhs, &cutact, &success, &cutislocal, &cutrank) );
6570 SCIPdebugMessage(
" -> delta = %g -> rhs: %g, act: %g\n", bestdelta, cutrhs, cutact);
6571 SCIP_CALL(
addCut(scip, sepa, sepadata, sol, cutcoefs, cutrhs, cutislocal, cutrank, ncuts, cutoff) );
6610 assert(result !=
NULL);
6623 if( ncols != nvars )
6625 MCFdebugMessage(
"%d variables but %d columns -> exit\n", nvars, ncols );
6638 colrowratio = (
SCIP_Real)ncols/(nrows+1e-9);
6642 assert(sepadata !=
NULL);
6651 if( colrowratio < MINCOLROWRATIO || colrowratio >
MAXCOLROWRATIO )
6660 if( sepadata->nmcfnetworks == -1 )
6668 for( i = 0; i < sepadata->nmcfnetworks; i++ )
6670 MCFdebugMessage(
" -> extracted network %d has %d nodes, %d (%d) arcs (uncapacitated), and %d commodities (modeltype: %s)\n",
6671 i, sepadata->mcfnetworks[i]->nnodes, sepadata->mcfnetworks[i]->narcs, sepadata->mcfnetworks[i]->nuncapacitatedarcs,
6672 sepadata->mcfnetworks[i]->ncommodities,
6674 SCIPdebug( mcfnetworkPrint(sepadata->mcfnetworks[i]) );
6677 #ifdef COUNTNETWORKVARIABLETYPES 6678 SCIP_CALL( printFlowSystemInfo(scip,sepadata->mcfnetworks,sepadata->nmcfnetworks));
6682 assert(sepadata->nmcfnetworks >= 0);
6683 assert(sepadata->mcfnetworks !=
NULL || sepadata->nmcfnetworks == 0);
6684 mcfnetworks = sepadata->mcfnetworks;
6685 nmcfnetworks = sepadata->nmcfnetworks;
6692 sepadata->lastroundsuccess =
FALSE;
6694 for( i = 0; i < nmcfnetworks && !cutoff; i++ )
6700 mcfnetwork = mcfnetworks[i];
6703 assert(mcfnetwork->
nnodes >= 2);
6704 assert(mcfnetwork->
narcs >= 1);
6711 MCFdebugMessage(
"MCF network has %d nodes and %d arcs. arc node ratio %.2f exceed --> exit\n",
6717 if( sepadata->separatesinglenodecuts )
6728 nodepartitionPrint(nodepartition);
6738 MCFdebugMessage(
"MCF network has %d nodes, %d arcs, %d commodities. Found %d MCF network cuts, cutoff = %u.\n",
6745 sepadata->lastroundsuccess =
TRUE;
6747 else if( ncuts > 0 )
6750 sepadata->lastroundsuccess =
TRUE;
6767 assert(scip !=
NULL);
6768 assert(sepa !=
NULL);
6786 assert(sepadata !=
NULL);
6787 assert(sepadata->mcfnetworks ==
NULL);
6788 assert(sepadata->nmcfnetworks == -1);
6806 assert(sepadata !=
NULL);
6808 sepadata->lastroundsuccess =
TRUE;
6825 assert(sepadata !=
NULL);
6828 for( i = 0; i < sepadata->nmcfnetworks; i++ )
6833 sepadata->nmcfnetworks = -1;
6895 sepadata->mcfnetworks =
NULL;
6896 sepadata->nmcfnetworks = -1;
6898 sepadata->lastroundsuccess =
TRUE;
6904 sepaExeclpMcf, sepaExecsolMcf,
6907 assert(sepa !=
NULL);
6919 "separating/mcf/nclusters",
6920 "number of clusters to generate in the shrunken network -- default separation",
6923 "separating/mcf/maxweightrange",
6924 "maximal valid range max(|weights|)/min(|weights|) of row weights",
6927 "separating/mcf/maxtestdelta",
6928 "maximal number of different deltas to try (-1: unlimited) -- default separation",
6931 "separating/mcf/trynegscaling",
6932 "should negative values also be tested in scaling?",
6935 "separating/mcf/fixintegralrhs",
6936 "should an additional variable be complemented if f0 = 0?",
6939 "separating/mcf/dynamiccuts",
6940 "should generated cuts be removed from the LP if they are no longer tight?",
6943 "separating/mcf/modeltype",
6944 "model type of network (0: auto, 1:directed, 2:undirected)",
6947 "separating/mcf/maxsepacuts",
6948 "maximal number of mcf cuts separated per separation round",
6951 "separating/mcf/maxsepacutsroot",
6952 "maximal number of mcf cuts separated per separation round in the root node -- default separation",
6955 "separating/mcf/maxinconsistencyratio",
6956 "maximum inconsistency ratio for separation at all",
6959 "separating/mcf/maxarcinconsistencyratio",
6960 "maximum inconsistency ratio of arcs not to be deleted",
6963 "separating/mcf/checkcutshoreconnectivity",
6964 "should we separate only if the cuts shores are connected?",
6967 "separating/mcf/separatesinglenodecuts",
6968 "should we separate inequalities based on single-node cuts?",
6971 "separating/mcf/separateflowcutset",
6972 "should we separate flowcutset inequalities on the network cuts?",
6975 "separating/mcf/separateknapsack",
6976 "should we separate knapsack cover inequalities on the network cuts?",
enum SCIP_Result SCIP_RESULT
int SCIPgetNLPBranchCands(SCIP *scip)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE mcfnetworkCreate(SCIP *scip, SCIP_MCFNETWORK **mcfnetwork)
#define DEFAULT_TRYNEGSCALING
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
int SCIPgetNVars(SCIP *scip)
#define SCIPallocMemory(scip, ptr)
static SCIP_RETCODE extractFlowRows(SCIP *scip, MCFDATA *mcfdata)
static void fixCommoditySigns(SCIP *scip, MCFDATA *mcfdata)
const char * SCIPvarGetName(SCIP_VAR *var)
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
SCIP_RETCODE SCIPincludeSepaMcf(SCIP *scip)
SCIP_Bool ** nodeflowinverted
static SCIP_RETCODE separateCuts(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
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, SCIP_Real maxweight, int *weightinds, int nweightinds, int rowlensum, 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)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
void SCIPsortInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
static SCIP_RETCODE nodepairqueueCreate(SCIP *scip, SCIP_MCFNETWORK *mcfnetwork, NODEPAIRQUEUE **nodepairqueue)
SCIP_RETCODE SCIPcaptureRow(SCIP *scip, SCIP_ROW *row)
static SCIP_RETCODE identifySourcesTargets(SCIP *scip, MCFDATA *mcfdata, SCIP_SEPADATA *sepadata, MCFEFFORTLEVEL *effortlevel)
SCIP_Real SCIPgetRowFeasibility(SCIP *scip, SCIP_ROW *row)
SCIP_Bool SCIPisStopped(SCIP *scip)
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
static SCIP_RETCODE extractFlow(SCIP *scip, MCFDATA *mcfdata, SCIP_Real maxflowvarflowrowratio, SCIP_Bool *failed)
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
SCIP_Bool SCIPisCutEfficacious(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
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)
static SCIP_RETCODE extractCapacities(SCIP *scip, MCFDATA *mcfdata)
#define SEPA_MAXBOUNDDIST
#define SCIPfreeMemoryArray(scip, ptr)
static SCIP_RETCODE identifyComponent(SCIP *scip, MCFDATA *mcfdata, int *nodevisited, int startv, int *compnodes, int *ncompnodes, int *comparcs, int *ncomparcs)
#define DEFAULT_MODELTYPE
int SCIProwGetNLPNonz(SCIP_ROW *row)
struct nodepairqueue NODEPAIRQUEUE
int SCIPgetNLPCols(SCIP *scip)
#define DEFAULT_MAXINCONSISTENCYRATIO
#define SCIPallocMemoryArray(scip, ptr, num)
static SCIP_RETCODE nodepartitionCreate(SCIP *scip, SCIP_MCFNETWORK *mcfnetwork, NODEPARTITION **nodepartition, int nclusters)
static void nodepairqueueFree(SCIP *scip, NODEPAIRQUEUE **nodepairqueue)
int SCIPsnprintf(char *t, int len, const char *s,...)
enum SCIP_Retcode SCIP_RETCODE
static SCIP_DECL_SORTINDCOMP(compCands)
void * SCIPpqueueFirst(SCIP_PQUEUE *pqueue)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
static SCIP_DECL_HASHKEYVAL(hashKeyValNodepairs)
SCIP_ROW ** SCIPgetLPRows(SCIP *scip)
#define DEFAULT_FIXINTEGRALRHS
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
static SCIP_DECL_SORTPTRCOMP(compNodepairs)
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)
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
#define DEFAULT_CHECKCUTSHORECONNECTIVITY
static NODEPAIRENTRY * nodepairqueueRemove(NODEPAIRQUEUE *nodepairqueue)
void SCIPpqueueFree(SCIP_PQUEUE **pqueue)
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
#define BMSclearMemoryArray(ptr, num)
SCIP_MCFMODELTYPE modeltype
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
SCIP_RETCODE SCIPaddCut(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool *infeasible)
SCIP_RETCODE SCIPsetSepaFree(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAFREE((*sepafree)))
SCIP_SEPADATA * SCIPsepaGetData(SCIP_SEPA *sepa)
const char * SCIPsepaGetName(SCIP_SEPA *sepa)
SCIP_Real SCIPgetRowMaxCoef(SCIP *scip, SCIP_ROW *row)
static SCIP_RETCODE mcfnetworkExtract(SCIP *scip, SCIP_SEPADATA *sepadata, SCIP_MCFNETWORK ***mcfnetworks, int *nmcfnetworks, MCFEFFORTLEVEL *effortlevel)
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)
#define MAXFLOWCANDDENSITY
SCIP_RETCODE SCIPsetSepaInitsol(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAINITSOL((*sepainitsol)))
SCIP_RETCODE SCIPgetLPColsData(SCIP *scip, SCIP_COL ***cols, int *ncols)
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)
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)
static SCIP_RETCODE findUncapacitatedArcs(SCIP *scip, MCFDATA *mcfdata)
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)
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
#define MAXFLOWVARFLOWROWRATIO
#define DEFAULT_MAXTESTDELTA
#define DEFAULT_SEPARATEFLOWCUTSET
static void getIncidentNodes(SCIP *scip, MCFDATA *mcfdata, SCIP_COL *col, int *sourcenode, int *targetnode)
int SCIPcolGetLPPos(SCIP_COL *col)
Constraint handler for knapsack constraints of the form , x binary and .
#define SCIPfreeMemory(scip, ptr)
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
static SCIP_DECL_SEPACOPY(sepaCopyMcf)
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
SCIP_Bool SCIPcolIsIntegral(SCIP_COL *col)
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
static void unionfindJoinSets(int *representatives, int rep1, int rep2)
void SCIPsortIntInt(int *intarray1, int *intarray2, int len)
#define DEFAULT_MAXSEPACUTSROOT
static SCIP_Bool nodeInPartition(NODEPARTITION *nodepartition, unsigned int partition, SCIP_Bool inverted, int v)
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
static void nodepartitionJoin(NODEPARTITION *nodepartition, int rep1, int rep2)
static SCIP_RETCODE createNewArc(SCIP *scip, MCFDATA *mcfdata, int source, int target, int *newarcid)
int SCIProwGetRank(SCIP_ROW *row)
int SCIPcalcHashtableSize(int minsize)
SCIP_Real SCIPgetRowLPFeasibility(SCIP *scip, SCIP_ROW *row)
SCIP_RETCODE SCIPaddPoolCut(SCIP *scip, SCIP_ROW *row)
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
static int nodepartitionIsConnected(SCIP *scip, SCIP_MCFNETWORK *mcfnetwork, NODEPARTITION *nodepartition, unsigned int partition)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
#define DEFAULT_MAXSEPACUTS
SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows)
static SCIP_RETCODE cleanupNetwork(SCIP *scip, MCFDATA *mcfdata)
SCIP_Real SCIPinfinity(SCIP *scip)
enum McfEffortLevel MCFEFFORTLEVEL
int SCIPcolGetNLPNonz(SCIP_COL *col)
SCIP_Longint SCIPgetNLPs(SCIP *scip)
#define DEFAULT_MAXWEIGHTRANGE
const char * SCIProwGetName(SCIP_ROW *row)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
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)
void * SCIPpqueueRemove(SCIP_PQUEUE *pqueue)
static SCIP_RETCODE mcfnetworkFill(SCIP *scip, SCIP_MCFNETWORK *mcfnetwork, MCFDATA *mcfdata, int *compnodeid, int *compnodes, int ncompnodes, int *comparcs, int ncomparcs)
SCIP_COL ** SCIPgetLPCols(SCIP *scip)
static void collectIncidentFlowCols(SCIP *scip, MCFDATA *mcfdata, SCIP_ROW *flowrow, int basecommodity)
public data structures and miscellaneous methods
struct nodepair NODEPAIRENTRY
void SCIPsepaSetData(SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata)
void SCIProwChgRank(SCIP_ROW *row, int rank)
multi-commodity-flow network cut separator
#define DEFAULT_NCLUSTERS
SCIP_Bool SCIPsepaWasLPDelayed(SCIP_SEPA *sepa)
SCIP_RETCODE SCIPsetSepaCopy(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPACOPY((*sepacopy)))
SCIP_RETCODE SCIPsetSepaExitsol(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAEXITSOL((*sepaexitsol)))
enum SCIP_McfModeltype SCIP_MCFMODELTYPE
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
static SCIP_DECL_HASHKEYEQ(hashKeyEqNodepairs)
static SCIP_DECL_SEPAEXITSOL(sepaExitsolMcf)
SCIP_ROW ** arccapacityrows
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)
#define SCIPreallocMemoryArray(scip, ptr, newnum)
static void deleteCommodity(SCIP *scip, MCFDATA *mcfdata, int k, SCIP_ROW **comrows, int nrows, int *ndelflowrows, int *ndelflowvars)
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
SCIP_Real SCIPfrac(SCIP *scip, SCIP_Real val)
#define UNCAPACITATEDARCSTRESHOLD
int SCIPgetDepth(SCIP *scip)
static void getNextFlowrow(SCIP *scip, MCFDATA *mcfdata, SCIP_ROW **nextrow, unsigned char *nextrowsign, SCIP_Bool *nextinvertcommodity)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
#define HASHSIZE_NODEPAIRS
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
static SCIP_RETCODE mcfnetworkFree(SCIP *scip, SCIP_MCFNETWORK **mcfnetwork)
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
#define MAXAGGRLEN(nvars)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
#define SCIPallocBufferArray(scip, ptr, num)
#define DEFAULT_MAXARCINCONSISTENCYRATIO
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
#define DEFAULT_SEPARATEKNAPSACK
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
SCIP_RETCODE SCIPpqueueInsert(SCIP_PQUEUE *pqueue, void *elem)
static int nodepartitionGetRepresentative(NODEPARTITION *nodepartition, int v)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
SCIP_RETCODE SCIPpqueueCreate(SCIP_PQUEUE **pqueue, int initsize, SCIP_Real sizefac, SCIP_DECL_SORTPTRCOMP((*ptrcomp)))
#define SCIPfreeMemoryArrayNull(scip, ptr)
#define DEFAULT_SEPARATESINGLENODECUTS
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
SCIP_Real ** nodeflowscales
static SCIP_RETCODE extractCapacityRows(SCIP *scip, MCFDATA *mcfdata)
#define MINCOMNODESFRACTION
static SCIP_DECL_SEPAEXECSOL(sepaExecsolMcf)
static void getFlowrowFit(SCIP *scip, MCFDATA *mcfdata, SCIP_ROW *row, int k, unsigned char *rowsign, SCIP_Bool *invertcommodity)
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
static SCIP_DECL_SEPAINITSOL(sepaInitsolMcf)
int SCIProwGetLPPos(SCIP_ROW *row)
static SCIP_DECL_SEPAEXECLP(sepaExeclpMcf)
SCIP_ROW *** nodeflowrows
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
SCIP_Real * arccapacityscales
#define SCIPfreeBufferArray(scip, ptr)
static SCIP_Bool nodepairqueueIsEmpty(NODEPAIRQUEUE *nodepairqueue)
static void unionfindInitSets(int *representatives, int nelems)
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)
static void invertCommodity(SCIP *scip, MCFDATA *mcfdata, int k, SCIP_ROW **comrows, int ncomrows, int *comcolids, int ncomcolids)
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
#define DEFAULT_DYNAMICCUTS
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
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)
static int unionfindGetRepresentative(int *representatives, int v)
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
SCIP_Real SCIPgetCutEfficacy(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
static void addFlowrowToCommodity(SCIP *scip, MCFDATA *mcfdata, SCIP_ROW *row, unsigned char rowsign, int *comcolids, int *ncomcolids)
static SCIP_DECL_HASHGETKEY(hashGetKeyNodepairs)
int SCIPgetNLPRows(SCIP *scip)
static SCIP_RETCODE extractNodes(SCIP *scip, MCFDATA *mcfdata)
struct nodepartition NODEPARTITION
static SCIP_DECL_SEPAFREE(sepaFreeMcf)
struct SCIP_SepaData SCIP_SEPADATA
static void nodepartitionFree(SCIP *scip, NODEPARTITION **nodepartition)
static SCIP_RETCODE createNewCommodity(SCIP *scip, MCFDATA *mcfdata)