51template<
typename TCost>
81 int infinity()
const {
return std::numeric_limits<int>::max(); }
153template<
typename TCost>
157 OGDF_ASSERT(this->checkProblem(G, lowerBound, upperBound, supply));
159 const int n = G.numberOfNodes();
160 const int m = G.numberOfEdges();
169 for (
node v : G.nodes) {
170 mcfSupply[i] = supply[v];
187 for (
edge e : G.edges) {
190 if (e->isSelfLoop()) {
195 mcfTail[i] = vIndex[e->source()];
196 mcfHead[i] = vIndex[e->target()];
197 mcfLb[i] = lowerBound[e];
198 mcfUb[i] = upperBound[e];
199 mcfCost[i] = cost[e];
214 edge eFirst = G.firstEdge();
215 flow[eFirst] = lowerBound[eFirst];
218 retCode = mcf(n, m - nSelfLoops, mcfSupply, mcfTail, mcfHead, mcfLb, mcfUb, mcfCost,
219 mcfFlow, mcfDual, &objVal);
225 for (
edge e : G.edges) {
226 if (e->isSelfLoop()) {
227 flow[e] = lowerBound[e];
231 flow[e] = mcfFlow[i];
241 for (
node v : G.nodes) {
242 dual[v] = mcfDual[i];
250template<
typename TCost>
256 root->successor = &nodes[1];
257 root->arc_id =
nullptr;
258 root->orientation =
false;
261 root->nr_of_nodes = nn + 1;
262 root->last = &nodes[nn];
265 TCost highCost = 1 + (nn + 1) * m_maxCost;
267 for (
int i = 1; i <= nn; ++i) {
269 if (supply[i - 1] >= 0) {
270 ep->
tail = &nodes[i];
274 ep->
head = &nodes[i];
281 nodes[i].father = root;
283 nodes[i].successor = &nodes[i + 1];
285 nodes[i].successor = root;
287 if (supply[i - 1] < 0) {
288 nodes[i].orientation =
false;
289 nodes[i].dual = -highCost;
291 nodes[i].orientation =
true;
292 nodes[i].dual = highCost;
294 nodes[i].flow = abs(supply[i - 1]);
295 nodes[i].nr_of_nodes = 1;
296 nodes[i].last = &nodes[i];
297 nodes[i].arc_id = ep;
299 start_n1 = start_arc;
303template<
typename TCost>
311 if (*pre !=
nullptr) {
319 while (*eplus !=
nullptr && !found) {
320 if (m_eps.less((*eplus)->cost + (*eplus)->head->dual, (*eplus)->tail->dual)) {
334 while (*eplus !=
nullptr && !found) {
335 if (m_eps.less((*eplus)->tail->dual, (*eplus)->head->dual + (*eplus)->cost)) {
349 while (*eplus != searchend && !found) {
350 if (m_eps.less((*eplus)->cost + (*eplus)->head->dual, (*eplus)->tail->dual)) {
363 while (*eplus !=
nullptr && !found) {
364 if (m_eps.less((*eplus)->tail->dual, (*eplus)->head->dual + (*eplus)->cost)) {
377 while (*eplus !=
nullptr && !found) {
378 if (m_eps.less((*eplus)->cost + (*eplus)->head->dual, (*eplus)->tail->dual)) {
392 while (*eplus != searchend && !found) {
393 if (m_eps.less((*eplus)->tail->dual, (*eplus)->head->dual + (*eplus)->cost)) {
416template<
typename TCost>
425 if (*pre !=
nullptr) {
430 searchend_n1 = *eplus;
432 while (*eplus !=
nullptr && !found) {
433 if (m_eps.less((*eplus)->cost + (*eplus)->head->dual, (*eplus)->tail->dual)) {
445 if (*pre !=
nullptr) {
450 searchend_n2 = *eplus;
452 while (*eplus !=
nullptr && !found) {
453 if (m_eps.less((*eplus)->tail->dual, (*eplus)->head->dual + (*eplus)->cost)) {
467 while (*eplus != searchend_n2 && !found) {
468 if (m_eps.less((*eplus)->tail->dual, (*eplus)->head->dual + (*eplus)->cost)) {
484 while (*eplus != searchend_n1 && !found) {
485 if (m_eps.less((*eplus)->cost + (*eplus)->head->dual, (*eplus)->tail->dual)) {
498 if (*pre !=
nullptr) {
503 searchend_n2 = *eplus;
505 while (*eplus !=
nullptr && !found) {
506 if (m_eps.less((*eplus)->tail->dual, (*eplus)->head->dual + (*eplus)->cost)) {
517 if (*pre !=
nullptr) {
522 searchend_n1 = *eplus;
524 while (*eplus !=
nullptr && !found) {
525 if (m_eps.less((*eplus)->cost + (*eplus)->head->dual, (*eplus)->tail->dual)) {
538 while (*eplus != searchend_n1 && !found) {
539 if (m_eps.less((*eplus)->cost + (*eplus)->head->dual, (*eplus)->tail->dual)) {
553 while (*eplus != searchend_n2 && !found) {
554 if (m_eps.less((*eplus)->tail->dual, (*eplus)->head->dual + (*eplus)->cost)) {
582template<
typename TCost>
602 int artificials = nn;
608 for (i = 1; i <= nn; ++i) {
617 int from = mcfTail[0];
618 int toh = mcfHead[0];
621 TCost c = mcfCost[0];
622 if (from <= 0 || from > nn || toh <= 0 || toh > nn || up < 0 || low > up || low < 0) {
625 TCost abs_c = c < 0 ? -c : c;
626 if (abs_c > m_maxCost) {
630 start_arc = &arcs[1];
631 start_arc->tail = &nodes[from];
632 start_arc->head = &nodes[toh];
634 start_arc->upper_bound = up - low;
635 start_arc->arcnum = 0;
636 supply[from - 1] -= low;
637 supply[toh - 1] += low;
638 lb_cost += start_arc->cost * low;
643 for (lower = 2; lower <= mm; ++lower) {
644 from = mcfTail[lower - 1];
645 toh = mcfHead[lower - 1];
646 low = mcfLb[lower - 1];
647 up = mcfUb[lower - 1];
648 c = mcfCost[lower - 1];
649 if (from <= 0 || from > nn || toh <= 0 || toh > nn || up < 0 || low > up || low < 0) {
652 abs_c = c < 0 ? -c : c;
653 if (abs_c > m_maxCost) {
659 ep->
tail = &nodes[from];
660 ep->
head = &nodes[toh];
664 supply[from - 1] -= low;
665 supply[toh - 1] += low;
666 lb_cost += ep->
cost * low;
672 bool feasible =
true;
688 bool finished =
false;
690 bool from_ub =
false;
691 startsearch = start_n1;
693 startsearchpre =
nullptr;
702 beacircle(&eplus, &pre, &from_ub);
704 if (eplus ==
nullptr) {
729 }
else if (delta > np->
flow) {
746 }
else if (delta > np->
flow) {
760 if (iminus ==
nullptr) {
776 bool artif_to_lb =
false;
777 if (artificials > 1) {
778 if (iminus == root || jminus == root) {
779 if (jplus != root && iplus != root) {
782 }
else if (eminus == eplus) {
791 if (iplus == root || jplus == root) {
801 if (eminus == eplus) {
807 s_orientation = eminus->
tail == iplus;
832 if (eplus->
tail == iplus) {
841 if (newsuc == iminus) {
850 bool s_orientation = (eplus->
tail != jplus);
853 bool eplus_ori = s_orientation;
870 while (nd != jminus) {
880 lastnode->
dual += sigma;
899 if (w_orientation == eplus_ori) {
900 w_flow = nd->
flow + delta;
902 w_flow = nd->
flow - delta;
910 s_orientation = w_orientation;
926 while (np != iplus) {
962 if (eminus == eplus) {
964 if (pre ==
nullptr) {
973 if (pre ==
nullptr) {
982 TCost wcost = eminus->
cost;
984 int wnum = eminus->
arcnum;
992 eplus->
tail = w_tail;
993 eplus->
head = w_head;
999 if (pre !=
nullptr) {
1022 if (artificials == 1) {
1032 if (e1 == start_b) {
1059 }
while (!finished);
1064 if (artificials != 0 && feasible) {
1073 }
while (np != root);
1076 while (ep !=
nullptr && feasible) {
1077 if (ep ==
nullptr) {
1080 if (ep->
tail == root && ep->
head == root) {
1093 while (np != root) {
1094 if (np->
flow != 0) {
1100 while (ep !=
nullptr) {
1104 *mcfObj = zfw + lb_cost;
1109 while (np != root) {
1113 mcfDual[root->name - 1] = root->dual;
1116 for (i = 0; i < mm; ++i) {
1117 mcfFlow[i] = mcfLb[i];
1121 while (np != root) {
1133 while (ep !=
nullptr) {
1143 for (i = 1; i <= nn; ++i)
1145 delete p[i]->arc_id;
1147 delete nodes[i].arc_id;
Declaration and implementation of Array class and Array algorithms.
Compare floating point numbers with epsilons and integral numbers with normal compare operators.
Includes declaration of graph class.
Decralation of GraphElement and GraphList classes.
Definition of ogdf::MinCostFlowModule class template.
Basic declarations, included by all source files.
The parameterized class Array implements dynamic arrays of type E.
Class for the representation of edges.
Data type for general directed graphs (adjacency list representation).
Interface for min-cost flow algorithms.
Computes a min-cost flow using a network simplex method.
void beacircle(arctype **eplus, arctype **pre, bool *from_ub)
void start(Array< int > &supply)
void beadouble(arctype **eplus, arctype **pre, bool *from_ub)
virtual bool call(const Graph &G, const EdgeArray< int > &lowerBound, const EdgeArray< int > &upperBound, const EdgeArray< TCost > &cost, const NodeArray< int > &supply, EdgeArray< int > &flow, NodeArray< TCost > &dual) override
Computes a min-cost flow in the directed graph G using a network simplex method.
int mcf(int mcfNrNodes, int mcfNrArcs, Array< int > &mcfSupply, Array< int > &mcfTail, Array< int > &mcfHead, Array< int > &mcfLb, Array< int > &mcfUb, Array< TCost > &mcfCost, Array< int > &mcfFlow, Array< TCost > &mcfDual, TCost *mcfObj)
Class for the representation of nodes.
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
RegisteredArray for nodes, edges and adjEntries of a graph.
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
#define OGDF_NEW_DELETE
Makes the class use OGDF's memory allocator.
Declaration of memory manager for allocating small pieces of memory.
TWeight infinity()
Helper function to get the maximum value for a given weight type.
The namespace for all OGDF objects.