Loading [MathJax]/extensions/tex2jax.js

Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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.