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