Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

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