1 /** \file
2 * \brief Definition of ogdf::MinCostFlowReinelt class template
3 *
4 * \author Carsten Gutwenger and Gerhard Reinelt
5 *
6 * \par License:
7 * This file is part of the Open Graph Drawing Framework (OGDF).
8 *
9 * \par
10 * Copyright (C)<br>
11 * See README.md in the OGDF root directory for details.
12 *
13 * \par
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * Version 2 or 3 as published by the Free Software Foundation;
17 * see the file LICENSE.txt included in the packaging of this file
18 * for details.
19 *
20 * \par
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * \par
27 * You should have received a copy of the GNU General Public
28 * License along with this program; if not, see
29 * http://www.gnu.org/copyleft/gpl.html
30 */
31
32 #pragma once
33
34 #include <ogdf/graphalg/MinCostFlowModule.h>
35 #include <ogdf/basic/EpsilonTest.h>
36
37 namespace ogdf {
38
39 //! Computes a min-cost flow using a network simplex method.
40 /**
41 * @ingroup ga-flow
42 */
43 template<typename TCost>
44 class MinCostFlowReinelt : public MinCostFlowModule<TCost>
45 {
46 public:
MinCostFlowReinelt()47 MinCostFlowReinelt()
48 : m_eps()
49 {
50 }
51
52 using MinCostFlowModule<TCost>::call;
53
54 /**
55 * \brief Computes a min-cost flow in the directed graph \p G using a network simplex method.
56 *
57 * \pre \p G must be connected, \p lowerBound[\a e] <= \p upperBound[\a e]
58 * for all edges \a e, and the sum over all supplies must be zero.
59 *
60 * @param G is the directed input graph.
61 * @param lowerBound gives the lower bound for the flow on each edge.
62 * @param upperBound gives the upper bound for the flow on each edge.
63 * @param cost gives the costs for each edge.
64 * @param supply gives the supply (or demand if negative) of each node.
65 * @param flow is assigned the computed flow on each edge.
66 * @param dual is assigned the computed dual variables.
67 * \return true iff a feasible min-cost flow exists.
68 */
69 virtual bool call(
70 const Graph &G, // directed graph
71 const EdgeArray<int> &lowerBound, // lower bound for flow
72 const EdgeArray<int> &upperBound, // upper bound for flow
73 const EdgeArray<TCost> &cost, // cost of an edge
74 const NodeArray<int> &supply, // supply (if neg. demand) of a node
75 EdgeArray<int> &flow, // computed flow
76 NodeArray<TCost> &dual) override; // computed dual variables
77
infinity()78 int infinity() const { return std::numeric_limits<int>::max(); }
79
80 private:
81
82 struct arctype;
83
84 struct nodetype {
85 nodetype *father; /* ->father in basis tree */
86 nodetype *successor; /* ->successor in preorder */
87 arctype *arc_id; /* ->arc (node,father) */
88 bool orientation; /* false<=>basic arc=(father->node)*/
89 TCost dual; /* value of dual variable */
90 int flow; /* flow in basic arc (node,father) */
91 int name; /* identification of node = node-nr*/
92 nodetype *last; /* last node in subtree */
93 int nr_of_nodes; /* number of nodes in subtree */
94 };
95
96 struct arctype {
97 arctype *next_arc; /* -> next arc in list */
98 nodetype *tail; /* -> tail of arc */
99 nodetype *head; /* -> head of arc */
100 TCost cost; /* cost of unit flow */
101 int upper_bound; /* capacity of arc */
102 int arcnum; /* number of arc in input */
103
104 OGDF_NEW_DELETE
105 };
106
107
108 int mcf(
109 int mcfNrNodes,
110 int mcfNrArcs,
111 Array<int> &mcfSupply,
112 Array<int> &mcfTail,
113 Array<int> &mcfHead,
114 Array<int> &mcfLb,
115 Array<int> &mcfUb,
116 Array<TCost> &mcfCost,
117 Array<int> &mcfFlow,
118 Array<TCost> &mcfDual,
119 TCost *mcfObj
120 );
121
122 void start(Array<int> &supply);
123
124 void beacircle(arctype **eplus, arctype **pre, bool *from_ub);
125 void beadouble(arctype **eplus, arctype **pre, bool *from_ub);
126
127 EpsilonTest m_eps;
128
129 Array<nodetype> nodes; /* node space */
130 Array<arctype> arcs; /* arc space */
131 //Array<nodetype *> p; /*used for starting procedure*/
132
133 nodetype *root = nullptr; /*->root of basis tree*/
134 nodetype rootStruct;
135
136 arctype *last_n1 = nullptr; /*->start for search for entering arc in N' */
137 arctype *last_n2 = nullptr; /*->start for search for entering arc in N''*/
138 arctype *start_arc = nullptr; /* -> initial arc list*/
139 arctype *start_b = nullptr; /* -> first basic arc*/
140 arctype *start_n1 = nullptr; /* -> first nonbasic arc in n'*/
141 arctype *start_n2 = nullptr; /* -> first nonbasic arc in n''*/
142 arctype *startsearch = nullptr; /* ->start of search for basis entering arc */
143 arctype *searchend = nullptr; /* ->end of search for entering arc in bea */
144 arctype *searchend_n1 = nullptr; /*->end of search for entering arc in N' */
145 arctype *searchend_n2 = nullptr; /*->end of search for entering arc in N''*/
146
147 //int artvalue; /*cost and upper_bound of artificial arc */
148 TCost m_maxCost = std::numeric_limits<TCost>::lowest(); // maximum of the cost of all input arcs
149
150 int nn = 0; /*number of original nodes*/
151 int mm = 0; /*number of original arcs*/
152 };
153
154 }
155
156 // Implementation
157
158 namespace ogdf {
159
160 // computes min-cost-flow, call front-end for mcf()
161 // returns true if a feasible minimum cost flow could be found
162 template<typename TCost>
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)163 bool MinCostFlowReinelt<TCost>::call(
164 const Graph &G,
165 const EdgeArray<int> &lowerBound,
166 const EdgeArray<int> &upperBound,
167 const EdgeArray<TCost> &cost,
168 const NodeArray<int> &supply,
169 EdgeArray<int> &flow,
170 NodeArray<TCost> &dual)
171 {
172 OGDF_ASSERT(this->checkProblem(G, lowerBound, upperBound, supply));
173
174 const int n = G.numberOfNodes();
175 const int m = G.numberOfEdges();
176
177 // assign indices 0, ..., n-1 to nodes in G
178 // (this is not guaranteed for v->index() )
179 NodeArray<int> vIndex(G);
180 // assigning supply
181 Array<int> mcfSupply(n);
182
183 int i = 0;
184 for(node v : G.nodes) {
185 mcfSupply[i] = supply[v];
186 vIndex[v] = ++i;
187 }
188
189
190 // allocation of arrays for arcs
191 Array<int> mcfTail(m);
192 Array<int> mcfHead(m);
193 Array<int> mcfLb(m);
194 Array<int> mcfUb(m);
195 Array<TCost> mcfCost(m);
196 Array<int> mcfFlow(m);
197 Array<TCost> mcfDual(n+1); // dual[n] = dual variable of root struct
198
199 // set input data in edge arrays
200 int nSelfLoops = 0;
201 i = 0;
202 for (edge e : G.edges) {
203 // We handle self-loops in the network already in the front-end
204 // (they are just set to the lower bound below when copying result)
205 if (e->isSelfLoop()) {
206 ++nSelfLoops;
207 continue;
208 }
209
210 mcfTail[i] = vIndex[e->source()];
211 mcfHead[i] = vIndex[e->target()];
212 mcfLb[i] = lowerBound[e];
213 mcfUb[i] = upperBound[e];
214 mcfCost[i] = cost[e];
215
216 ++i;
217 }
218
219
220 int retCode = 0; // return (error or success) code
221 TCost objVal; // value of flow
222
223 // call actual min-cost-flow function
224 // mcf does not support single nodes
225 if (n > 1) {
226 //mcf does not support single edges
227 if (m < 2) {
228 if (m == 1) {
229 edge eFirst = G.firstEdge();
230 flow[eFirst] = lowerBound[eFirst];
231 }
232 } else {
233 retCode = mcf(n, m - nSelfLoops, mcfSupply, mcfTail, mcfHead, mcfLb, mcfUb, mcfCost, mcfFlow, mcfDual, &objVal);
234 }
235 }
236
237 // copy resulting flow for return
238 i = 0;
239 for (edge e : G.edges) {
240 if (e->isSelfLoop()) {
241 flow[e] = lowerBound[e];
242 continue;
243 }
244
245 flow[e] = mcfFlow[i];
246 if (retCode == 0) {
247 OGDF_ASSERT(flow[e] >= lowerBound[e]);
248 OGDF_ASSERT(flow[e] <= upperBound[e]);
249 }
250 ++i;
251 }
252
253 // copy resulting dual values for return
254 i = 0;
255 for (node v : G.nodes) {
256 dual[v] = mcfDual[i];
257 ++i;
258 }
259
260 // successful if retCode == 0
261 return retCode == 0;
262 }
263
264
265 template<typename TCost>
start(Array<int> & supply)266 void MinCostFlowReinelt<TCost>::start(Array<int> &supply)
267 {
268 // determine intial basis tree and initialize data structure
269
270 /* initialize artificial root node */
271 root->father = root;
272 root->successor = &nodes[1];
273 root->arc_id = nullptr;
274 root->orientation = false;
275 root->dual = 0;
276 root->flow = 0;
277 root->nr_of_nodes = nn + 1;
278 root->last = &nodes[nn];
279 root->name = nn + 1;
280 // artificials = nn; moved to mcf() [CG]
281 TCost highCost = 1 + (nn+1) * m_maxCost;
282
283 for (int i = 1; i <= nn; ++i) { /* for every node an artificial arc is created */
284 arctype *ep = new arctype;
285 if (supply[i - 1] >= 0) {
286 ep->tail = &nodes[i];
287 ep->head = root;
288 } else {
289 ep->tail = root;
290 ep->head = &nodes[i];
291 }
292 ep->cost = highCost;
293 ep->upper_bound = infinity();
294 ep->arcnum = mm + i - 1;
295 ep->next_arc = start_b;
296 start_b = ep;
297 nodes[i].father = root;
298 if (i < nn)
299 nodes[i].successor = &nodes[i+1];
300 else
301 nodes[i].successor = root;
302 if (supply[i - 1] < 0) {
303 nodes[i].orientation = false;
304 nodes[i].dual = -highCost;
305 } else {
306 nodes[i].orientation = true;
307 nodes[i].dual = highCost;
308 }
309 nodes[i].flow = abs(supply[i - 1]);
310 nodes[i].nr_of_nodes = 1;
311 nodes[i].last = &nodes[i];
312 nodes[i].arc_id = ep;
313 } /* for i */
314 start_n1 = start_arc;
315 } /*start*/
316
317
318 // circle variant for determine basis entering arc
319 template<typename TCost>
beacircle(arctype ** eplus,arctype ** pre,bool * from_ub)320 void MinCostFlowReinelt<TCost>::beacircle(
321 arctype **eplus,
322 arctype **pre,
323 bool *from_ub)
324 {
325 //the first arc with negative reduced costs is taken, but the search is
326 //started at the successor of the successor of eplus in the last iteration
327
328 bool found = false; /* true<=>entering arc found */
329
330 *pre = startsearch;
331 if (*pre != nullptr) {
332 *eplus = (*pre)->next_arc;
333 } else {
334 *eplus = nullptr;
335 }
336 searchend = *eplus;
337
338 if (!*from_ub) {
339
340 while (*eplus != nullptr && !found) { /* search in n' for an arc with negative reduced costs */
341 if (m_eps.less((*eplus)->cost + (*eplus)->head->dual, (*eplus)->tail->dual)) {
342 found = true;
343 } else {
344 *pre = *eplus; /* save predecessor */
345 *eplus = (*eplus)->next_arc; /* go to next arc */
346 }
347 } /* while */
348
349 if (!found) { /* entering arc still not found */
350 /* search in n'' */
351 *from_ub = true;
352 *eplus = start_n2;
353 *pre = nullptr;
354
355 while (*eplus != nullptr && !found) {
356 if (m_eps.less((*eplus)->tail->dual, (*eplus)->head->dual + (*eplus)->cost)) {
357 found = true;
358 } else {
359 *pre = *eplus; /* save predecessor */
360 *eplus = (*eplus)->next_arc; /* go to next arc */
361 }
362 } /* while */
363
364
365 if (!found) { /* search again in n' */
366 *from_ub = false;
367 *eplus = start_n1;
368 *pre = nullptr;
369
370 while (*eplus != searchend && !found) {
371 if (m_eps.less((*eplus)->cost + (*eplus)->head->dual, (*eplus)->tail->dual)) {
372 found = true;
373 } else {
374 *pre = *eplus; /* save predecessor */
375 *eplus = (*eplus)->next_arc; /* go to next arc */
376 }
377 } /* while */
378
379 } /* search in n'' */
380 } /* serch again in n' */
381 } /* if from_ub */
382 else { /* startsearch in n'' */
383
384 while (*eplus != nullptr && !found) {
385 if (m_eps.less((*eplus)->tail->dual, (*eplus)->head->dual + (*eplus)->cost)) {
386 found = true;
387 } else {
388 *pre = *eplus; /* save predecessor */
389 *eplus = (*eplus)->next_arc; /* go to next arc */
390 }
391 } /* while */
392
393 if (!found) { /* search now in n' */
394 *from_ub = false;
395 *eplus = start_n1;
396 *pre = nullptr;
397
398 while (*eplus != nullptr && !found) {
399 if (m_eps.less((*eplus)->cost + (*eplus)->head->dual, (*eplus)->tail->dual)) {
400 found = true;
401 } else {
402 *pre = *eplus; /* save predecessor */
403 *eplus = (*eplus)->next_arc; /* go to next arc */
404 }
405 } /* while */
406
407
408 if (!found) { /* search again in n'' */
409 *from_ub = true;
410 *eplus = start_n2;
411 *pre = nullptr;
412
413 while (*eplus != searchend && !found) {
414 if (m_eps.less((*eplus)->tail->dual, (*eplus)->head->dual + (*eplus)->cost)) {
415 found = true;
416 } else {
417 *pre = *eplus; /* save predecessor */
418 *eplus = (*eplus)->next_arc; /* go to next arc */
419 }
420 } /* while */
421
422 } /* search in n' */
423 } /* search in n'' */
424 } /* from_ub = true */
425
426
427
428 if (!found) {
429 *pre = nullptr;
430 *eplus = nullptr;
431 } else {
432 startsearch = (*eplus)->next_arc;
433 }
434
435 } /* beacircle */
436
437
438 // doublecircle variant for determine basis entering arc
439 template<typename TCost>
beadouble(arctype ** eplus,arctype ** pre,bool * from_ub)440 void MinCostFlowReinelt<TCost>::beadouble(
441 arctype **eplus,
442 arctype **pre,
443 bool *from_ub)
444 {
445 /* search as in procedure beacircle, but in each list the search started is
446 at the last movement
447 */
448 bool found = false; /* true<=>entering arc found */
449
450 if (!*from_ub) {
451 *pre = last_n1;
452 if (*pre != nullptr)
453 *eplus = (*pre)->next_arc;
454 else
455 *eplus = nullptr;
456 searchend_n1 = *eplus;
457
458 while (*eplus != nullptr && !found) { /* search in n' for an arc with negative reduced costs */
459 if (m_eps.less((*eplus)->cost + (*eplus)->head->dual, (*eplus)->tail->dual)) {
460 found = true;
461 } else {
462 *pre = *eplus; /* save predecessor */
463 *eplus = (*eplus)->next_arc; /* go to next arc */
464 }
465 } /* while */
466
467 if (!found) { /* entering arc still not found */
468 /* search in n'' beginning at the last movement */
469 *from_ub = true;
470 *pre = last_n2;
471 if (*pre != nullptr)
472 *eplus = (*pre)->next_arc;
473 else
474 *eplus = nullptr;
475 searchend_n2 = *eplus;
476
477 while (*eplus != nullptr && !found) {
478 if (m_eps.less((*eplus)->tail->dual, (*eplus)->head->dual + (*eplus)->cost)) {
479 found = true;
480 } else {
481 *pre = *eplus; /* save predecessor */
482 *eplus = (*eplus)->next_arc; /* go to next arc */
483 }
484
485 } /* while */
486
487 if (!found) { /* entering arc still not found */
488 /* search in n'' in the first part of the list */
489 *eplus = start_n2;
490 *pre = nullptr;
491
492 while (*eplus != searchend_n2 && !found) {
493 if (m_eps.less((*eplus)->tail->dual, (*eplus)->head->dual + (*eplus)->cost)) {
494 found = true;
495 } else {
496 *pre = *eplus; /* save predecessor */
497 *eplus = (*eplus)->next_arc; /* go to next arc */
498 }
499
500 } /* while */
501
502
503 if (!found) {
504 /* search again in n' in the first part of the list*/
505 *from_ub = false;
506 *eplus = start_n1;
507 *pre = nullptr;
508
509 while (*eplus != searchend_n1 && !found) {
510 if (m_eps.less((*eplus)->cost + (*eplus)->head->dual, (*eplus)->tail->dual)) {
511 found = true;
512 } else {
513 *pre = *eplus; /* save predecessor */
514 *eplus = (*eplus)->next_arc; /* go to next arc */
515 }
516 } /* while */
517 } /* first part n' */
518 } /* first part n'' */
519 } /* second part n'' */
520 } /* if from_ub */
521 else { /* startsearch in n'' */
522 *pre = last_n2;
523 if (*pre != nullptr)
524 *eplus = (*pre)->next_arc;
525 else
526 *eplus = nullptr;
527 searchend_n2 = *eplus;
528
529 while (*eplus != nullptr && !found) {
530 if (m_eps.less((*eplus)->tail->dual, (*eplus)->head->dual + (*eplus)->cost)) {
531 found = true;
532 } else {
533 *pre = *eplus; /* save predecessor */
534 *eplus = (*eplus)->next_arc; /* go to next arc */
535 }
536 } /* while */
537
538 if (!found) { /* search now in n' beginning at the last movement */
539 *from_ub = false;
540 *pre = last_n1;
541 if (*pre != nullptr)
542 *eplus = (*pre)->next_arc;
543 else
544 *eplus = nullptr;
545 searchend_n1 = *eplus;
546
547 while (*eplus != nullptr && !found) {
548 if (m_eps.less((*eplus)->cost + (*eplus)->head->dual, (*eplus)->tail->dual)) {
549 found = true;
550 } else {
551 *pre = *eplus; /* save predecessor */
552 *eplus = (*eplus)->next_arc; /* go to next arc */
553 }
554 } /* while */
555
556
557 if (!found) { /* search now in n' in the first part */
558 *eplus = start_n1;
559 *pre = nullptr;
560
561 while (*eplus != searchend_n1 && !found) {
562 if (m_eps.less((*eplus)->cost + (*eplus)->head->dual, (*eplus)->tail->dual)) {
563 found = true;
564 } else {
565 *pre = *eplus; /* save predecessor */
566 *eplus = (*eplus)->next_arc; /* go to next arc */
567 }
568 } /* while */
569
570
571 if (!found) { /* search again in n'' in the first part */
572 *from_ub = true;
573 *eplus = start_n2;
574 *pre = nullptr;
575
576 while (*eplus != searchend_n2 && !found) {
577 if (m_eps.less((*eplus)->tail->dual, (*eplus)->head->dual + (*eplus)->cost)) {
578 found = true;
579 } else {
580 *pre = *eplus; /* save predecessor */
581 *eplus = (*eplus)->next_arc; /* go to next arc */
582 }
583 } /* while */
584 } /* first part of n'' */
585 } /* first part of n' */
586 } /* second part of n' */
587 } /* from_ub = true */
588
589
590
591 if (!found) {
592 *pre = nullptr;
593 *eplus = nullptr;
594 return;
595 }
596
597 if (*from_ub)
598 last_n2 = (*eplus)->next_arc;
599 else
600 last_n1 = (*eplus)->next_arc;
601
602 } /* beadouble */
603
604
605 // Min Cost Flow Function
606 template<typename TCost>
mcf(int mcfNrNodes,int mcfNrArcs,Array<int> & supply,Array<int> & mcfTail,Array<int> & mcfHead,Array<int> & mcfLb,Array<int> & mcfUb,Array<TCost> & mcfCost,Array<int> & mcfFlow,Array<TCost> & mcfDual,TCost * mcfObj)607 int MinCostFlowReinelt<TCost>::mcf(
608 int mcfNrNodes,
609 int mcfNrArcs,
610 Array<int> &supply,
611 Array<int> &mcfTail,
612 Array<int> &mcfHead,
613 Array<int> &mcfLb,
614 Array<int> &mcfUb,
615 Array<TCost> &mcfCost,
616 Array<int> &mcfFlow,
617 Array<TCost> &mcfDual,
618 TCost *mcfObj)
619 {
620 int i;
621 int low,up;
622
623 /* 1: Allocations (malloc's no longer required) */
624
625 root = &rootStruct;
626
627 /* 2: Initializations */
628
629 /* Number of nodes/arcs */
630 nn = mcfNrNodes;
631 OGDF_ASSERT(nn >= 2);
632 mm = mcfNrArcs;
633 OGDF_ASSERT(mm >= 2);
634
635 // number of artificial basis arcs
636 int artificials = nn;
637
638
639 /* Node space and pointers to nodes */
640 nodes.init(nn+1);
641 nodes[0].name = -1; // for debuggin, should not occur(?)
642 for(i = 1; i <= nn; ++i)
643 nodes[i].name = i;
644
645 /* Arc space and arc data */
646 arcs.init(mm+1);
647
648 TCost lb_cost = 0; // cost of lower bound
649 m_maxCost = 0;
650 int from = mcfTail[0]; // name of tail (input)
651 int toh = mcfHead[0]; // name of head (input)
652 low = mcfLb[0];
653 up = mcfUb[0];
654 TCost c = mcfCost[0]; // cost (input)
655 if (from <= 0 || from > nn || toh <= 0 || toh > nn || up < 0 || low > up || low < 0) {
656 return 4;
657 }
658 TCost abs_c = c < 0 ? -c : c;
659 if (abs_c > m_maxCost) {
660 m_maxCost = abs_c;
661 }
662
663 start_arc = &arcs[1];
664 start_arc->tail = &nodes[from];
665 start_arc->head = &nodes[toh];
666 start_arc->cost = c;
667 start_arc->upper_bound = up - low;
668 start_arc->arcnum = 0;
669 supply[from - 1] -= low;
670 supply[toh - 1] += low;
671 lb_cost += start_arc->cost * low;
672
673 arctype *e = start_arc;
674
675 int lower; // lower bound (input)
676 for (lower = 2; lower <= mm; ++lower) {
677 from = mcfTail[lower-1];
678 toh = mcfHead[lower-1];
679 low = mcfLb[lower-1];
680 up = mcfUb[lower-1];
681 c = mcfCost[lower-1];
682 if (from <= 0 || from > nn || toh <= 0 || toh > nn || up < 0 || low > up || low < 0) {
683 return 4;
684 }
685 abs_c = c < 0 ? -c : c;
686 if (abs_c > m_maxCost) {
687 m_maxCost = abs_c;
688 }
689
690 arctype *ep = &arcs[lower];
691 e->next_arc = ep;
692 ep->tail = &nodes[from];
693 ep->head = &nodes[toh];
694 ep->cost = c;
695 ep->upper_bound = up - low;
696 ep->arcnum = lower-1;
697 supply[from-1] -= low;
698 supply[toh-1] += low;
699 lb_cost += ep->cost * low;
700 e = ep;
701 }
702
703 e->next_arc = nullptr;
704 // feasible = true <=> feasible solution exists
705 bool feasible = true;
706
707
708 /* 3: Starting solution */
709
710 start_n1 = nullptr;
711 start_n2 = nullptr;
712 start_b = nullptr;
713
714 start(supply);
715
716 int step = 1; /* initialize iteration counter */
717
718 /* 4: Iteration loop */
719
720 /* 4.1: Determine basis entering arc */
721
722 // finished = true <=> iteration finished
723 bool finished = false;
724 // from_ub = true <=> entering arc at upper bound
725 bool from_ub = false;
726 startsearch = start_n1;
727 #if 0
728 startsearchpre = nullptr;
729 #endif
730 last_n1 = nullptr;
731 last_n2 = nullptr;
732 nodetype *np; // general nodeptr
733
734 do {
735 arctype *eplus; // ->basis entering arc
736 arctype *pre; // ->predecessor of eplus in list
737 beacircle(&eplus, &pre, &from_ub);
738
739 if (eplus == nullptr) {
740 finished = true;
741 } else {
742
743 nodetype *iplus = eplus->tail; // -> tail of basis entering arc
744 nodetype *jplus = eplus->head; // -> head of basis entering arc
745
746 /* 4.2: Determine leaving arc and maximal flow change */
747
748 int delta = eplus->upper_bound; // maximal flow change
749 nodetype *iminus = nullptr; // -> tail of basis leaving arc
750 nodetype *p1 = iplus;
751 nodetype *p2 = jplus;
752
753 bool to_ub; // to_ub = true <=> leaving arc goes to upperbound
754 bool xchange; // xchange = true <=> exchange iplus and jplus
755 while (p1 != p2) {
756 if (p1->nr_of_nodes <= p2->nr_of_nodes) {
757 np = p1;
758 if (from_ub == np->orientation) {
759 if (delta > np->arc_id->upper_bound - np->flow) {
760 iminus = np;
761 delta = np->arc_id->upper_bound - np->flow;
762 xchange = false;
763 to_ub = true;
764 }
765 }
766 else if (delta > np->flow) {
767 iminus = np;
768 delta = np->flow;
769 xchange = false;
770 to_ub = false;
771 }
772 p1 = np->father;
773 continue;
774 }
775 np = p2;
776 if (from_ub != np->orientation) {
777 if (delta > np->arc_id->upper_bound - np->flow) {
778 iminus = np;
779 delta = np->arc_id->upper_bound - np->flow;
780 xchange = true;
781 to_ub = true;
782 }
783 }
784 else if (delta > np->flow) {
785 iminus = np;
786 delta = np->flow;
787 xchange = true;
788 to_ub = false;
789 }
790 p2 = np->father;
791 }
792 // paths from iplus and jplus to root meet at w
793 nodetype *w = p1;
794 nodetype *iw;
795 nodetype *jminus; // -> head of basis leaving arc
796
797 arctype *eminus; /// ->basis leaving arc
798 if (iminus == nullptr) {
799 to_ub = !from_ub;
800 eminus = eplus;
801 iminus = iplus;
802 jminus = jplus;
803 }
804 else {
805 if (xchange) {
806 iw = jplus;
807 jplus = iplus;
808 iplus = iw;
809 }
810 jminus = iminus->father;
811 eminus = iminus->arc_id;
812 }
813
814 // artif_to_lb = true <=> artif. arc goes to lower bound
815 bool artif_to_lb = false;
816 if (artificials > 1) {
817 if (iminus == root || jminus == root) {
818 if (jplus != root && iplus != root) {
819 artificials--;
820 artif_to_lb = true;
821 }
822 else if (eminus == eplus) {
823 if (from_ub) {
824 artificials--;
825 artif_to_lb = true;
826 } else
827 artificials++;
828 }
829 }
830 else {
831 if (iplus == root || jplus == root)
832 artificials++;
833 }
834 }
835
836 /* 4.3: Update of data structure */
837
838 TCost sigma; // change of dual variables
839
840 if (eminus == eplus) {
841 if (from_ub) delta = -delta;
842
843 bool s_orientation;
844 s_orientation = eminus->tail == iplus;
845
846 np = iplus;
847 while (np != w) {
848 if (np->orientation == s_orientation) {
849 np->flow -= delta;
850 }
851 else {
852 np->flow += delta;
853 }
854 np = np->father;
855 }
856
857 np = jplus;
858 while (np != w) {
859 if (np->orientation == s_orientation) {
860 np->flow += delta;
861 }
862 else {
863 np->flow -= delta;
864 }
865 np = np->father;
866 }
867
868 } else {
869 /* 4.3.2.1 : initialize sigma */
870
871 if (eplus->tail == iplus)
872 sigma = eplus->cost + jplus->dual - iplus->dual;
873 else
874 sigma = jplus->dual - iplus->dual - eplus->cost;
875
876 // 4.3.2.2 : find new succ. of jminus if current succ. is iminus
877
878 nodetype *newsuc = jminus->successor; // -> new successor
879 if (newsuc == iminus) {
880 for (i= 1; i <= iminus->nr_of_nodes; ++i) {
881 newsuc = newsuc->successor;
882 }
883 }
884
885 /* 4.3.2.3 : initialize data for iplus */
886
887 nodetype *s_father = jplus; // save area
888 bool s_orientation = (eplus->tail != jplus);
889
890 // eplus_ori = true <=> eplus = (iplus,jplus)
891 bool eplus_ori = s_orientation;
892
893 int s_flow;
894 if (from_ub) {
895 s_flow = eplus->upper_bound - delta;
896 delta = -delta;
897 } else {
898 s_flow = delta;
899 }
900
901 arctype *s_arc_id = eminus;
902 int oldnumber = 0;
903 nodetype *nd = iplus; // -> current node
904 nodetype *f = nd->father; // ->father of nd
905
906 /* 4.3.2.4 : traverse subtree under iminus */
907
908 while (nd != jminus) {
909 nodetype *pred = f; // ->predecessor of current node
910 while (pred->successor != nd) pred = pred->successor;
911 nodetype *lastnode = nd; // -> last node of subtree
912 i = 1;
913 int non = nd->nr_of_nodes - oldnumber;
914 while (i < non) {
915 lastnode = lastnode->successor;
916 lastnode->dual += sigma;
917 i++;
918 }
919 nd->dual += sigma;
920 pred->successor = lastnode->successor;
921
922 if (nd != iminus) lastnode->successor = f;
923 else lastnode->successor = jplus->successor;
924
925 nodetype *w_father = nd; // save area
926 arctype *w_arc_id = nd->arc_id; // save area
927
928 bool w_orientation;
929 w_orientation = nd->arc_id->tail != nd;
930
931 int w_flow;
932 if (w_orientation == eplus_ori) {
933 w_flow = nd->flow + delta;
934 }
935 else {
936 w_flow = nd->flow - delta;
937 }
938
939 nd->father = s_father;
940 nd->orientation = s_orientation;
941 nd->arc_id = s_arc_id;
942 nd->flow = s_flow;
943 s_father = w_father;
944 s_orientation = w_orientation;
945 s_arc_id = w_arc_id;
946 s_flow = w_flow;
947
948 oldnumber = nd->nr_of_nodes;
949 nd = f;
950 f = f->father;
951
952 }
953
954 jminus->successor = newsuc;
955 jplus->successor = iplus;
956
957 // 4.3.2.5: assign new nr_of_nodes in path from iminus to iplus
958
959 oldnumber = iminus->nr_of_nodes;
960 np = iminus;
961 while (np != iplus) {
962 np->nr_of_nodes = oldnumber - np->father->nr_of_nodes;
963 np = np->father;
964 }
965
966 iplus->nr_of_nodes = oldnumber;
967
968 // 4.3.2.6: update flows and nr_of_nodes in path from jminus to w
969
970 np = jminus;
971 while (np != w) {
972 np->nr_of_nodes -= oldnumber;
973 if (np->orientation != eplus_ori) {
974 np->flow += delta;
975 }
976 else {
977 np->flow -= delta;
978 }
979 np = np->father;
980 }
981
982 // 4.3.2.7 update flows and nr_of_nodes in path from jplus to w
983
984 np = jplus;
985 while (np != w) {
986 np->nr_of_nodes += oldnumber;
987 if (np->orientation == eplus_ori) {
988 np->flow += delta;
989 }
990 else {
991 np->flow -= delta;
992 }
993 np = np->father;
994 }
995
996 }
997
998 /* 4.4: Update lists B, N' and N'' */
999
1000 if (eminus == eplus) {
1001 if (!from_ub) {
1002 if (pre == nullptr)
1003 start_n1 = eminus->next_arc;
1004 else
1005 pre->next_arc = eminus->next_arc;
1006
1007 eminus->next_arc = start_n2;
1008 start_n2 = eminus;
1009 } else {
1010 if (pre == nullptr)
1011 start_n2 = eminus->next_arc;
1012 else
1013 pre->next_arc = eminus->next_arc;
1014 eminus->next_arc = start_n1;
1015 start_n1 = eminus;
1016 }
1017 } else {
1018 TCost wcost = eminus->cost;
1019 int wub = eminus->upper_bound;
1020 int wnum = eminus->arcnum;
1021 nodetype *w_head = eminus->head;
1022 nodetype *w_tail = eminus->tail;
1023 eminus->tail = eplus->tail;
1024 eminus->head = eplus->head;
1025 eminus->upper_bound = eplus->upper_bound;
1026 eminus->arcnum = eplus->arcnum;
1027 eminus->cost = eplus->cost;
1028 eplus->tail = w_tail;
1029 eplus->head = w_head;
1030 eplus->upper_bound = wub;
1031 eplus->cost = wcost;
1032 eplus->arcnum = wnum;
1033 arctype *ep = eplus;
1034
1035 if (pre != nullptr)
1036 pre->next_arc = ep->next_arc;
1037 else {
1038 if (from_ub) start_n2 = ep->next_arc;
1039 else start_n1 = ep->next_arc;
1040 }
1041
1042 if (to_ub) {
1043 ep->next_arc = start_n2;
1044 start_n2 = ep;
1045 } else {
1046 if (!artif_to_lb) {
1047 ep->next_arc = start_n1;
1048 start_n1 = ep;
1049 }
1050 }
1051 }
1052
1053 step++;
1054
1055 /* 4.5: Eliminate artificial arcs and artificial root node */
1056
1057 if (artificials == 1) {
1058 artificials = 0;
1059 nodetype *nd = root->successor;
1060 arctype *e1 = nd->arc_id;
1061
1062 if (nd->flow>0) {
1063 feasible = false;
1064 finished = true;
1065 } else {
1066 feasible = true;
1067 if (e1 == start_b) {
1068 start_b = e1->next_arc;
1069 } else {
1070 e = start_b;
1071 while (e->next_arc != e1)
1072 e = e->next_arc;
1073 e->next_arc = e1->next_arc;
1074 }
1075
1076 iw = root;
1077 root = root->successor;
1078 root->father = root;
1079 sigma = root->dual;
1080
1081 np = root;
1082 while (np->successor != iw) {
1083 np->dual -= sigma;
1084 np = np->successor;
1085 }
1086
1087 np->dual -= sigma;
1088 np->successor = root;
1089
1090 }
1091
1092 }
1093
1094 }
1095
1096 } while (!finished);
1097
1098 /* 5: Return results */
1099
1100 /* Feasible solution? */
1101 if (artificials != 0
1102 && feasible) {
1103 np = root->successor;
1104 do {
1105 if (np->father == root
1106 && np->flow > 0) {
1107 feasible = false;
1108 np = root;
1109 }
1110 else
1111 np = np->successor;
1112 } while (np != root);
1113
1114 arctype *ep = start_n2;
1115 while (ep != nullptr && feasible) {
1116 if (ep == nullptr)
1117 break;
1118 if (ep->tail == root && ep->head == root)
1119 feasible = false;
1120 ep = ep->next_arc;
1121 }
1122 }
1123
1124 int retValue = 0;
1125
1126 if (feasible) {
1127 /* Objective function value */
1128 TCost zfw = 0; // current total cost
1129 np = root->successor;
1130 while (np != root) {
1131 if (np->flow != 0) {
1132 zfw += np->flow * np->arc_id->cost;
1133 }
1134 np = np->successor;
1135 }
1136 arctype *ep = start_n2;
1137 while (ep != nullptr) {
1138 zfw += ep->cost * ep->upper_bound;
1139 ep = ep->next_arc;
1140 }
1141 *mcfObj = zfw + lb_cost;
1142
1143 /* Dual variables */
1144 // CG: removed computation of duals
1145 np = root->successor;
1146 while (np != root) {
1147 mcfDual[np->name-1] = np->dual;
1148 np = np->successor;
1149 }
1150 mcfDual[root->name-1] = root->dual;
1151
1152 /* Arc flows */
1153 for (i = 0; i < mm; ++i)
1154 mcfFlow[i] = mcfLb[i];
1155
1156 np = root->successor;
1157 while (np != root) {
1158 // flow on artificial arcs has to be 0 to be ignored! [CG]
1159 OGDF_ASSERT(np->arc_id->arcnum < mm || np->flow == 0);
1160
1161 if (np->arc_id->arcnum < mm)
1162 mcfFlow[np->arc_id->arcnum] += np->flow;
1163
1164 np = np->successor;
1165 }
1166
1167 ep = start_n2;
1168 while (ep != nullptr) {
1169 mcfFlow[ep->arcnum] += ep->upper_bound;
1170 ep = ep->next_arc;
1171 }
1172
1173 } else {
1174 retValue = 10;
1175 }
1176
1177 // deallocate artificial arcs
1178 for(i = 1; i <= nn; ++i)
1179 #if 0
1180 delete p[i]->arc_id;
1181 #endif
1182 delete nodes[i].arc_id;
1183
1184 return retValue;
1185 }
1186
1187 }
1188