Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

MinCostFlowReinelt.h
Go to the documentation of this file.
1 
32 #pragma once
33 
34 #include <ogdf/basic/EpsilonTest.h>
36 
37 namespace ogdf {
38 
40 
43 template<typename TCost>
44 class MinCostFlowReinelt : public MinCostFlowModule<TCost> {
45 public:
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 
75 private:
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 
101  int mcf(int mcfNrNodes, int mcfNrArcs, Array<int>& mcfSupply, Array<int>& mcfTail,
102  Array<int>& mcfHead, Array<int>& mcfLb, Array<int>& mcfUb, Array<TCost>& mcfCost,
103  Array<int>& mcfFlow, Array<TCost>& mcfDual, TCost* mcfObj);
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 
141 namespace ogdf {
142 
143 // computes min-cost-flow, call front-end for mcf()
144 // returns true if a feasible minimum cost flow could be found
145 template<typename TCost>
146 bool MinCostFlowReinelt<TCost>::call(const Graph& G, const EdgeArray<int>& lowerBound,
147  const EdgeArray<int>& upperBound, const EdgeArray<TCost>& cost,
148  const NodeArray<int>& supply, EdgeArray<int>& flow, NodeArray<TCost>& dual) {
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() )
156  NodeArray<int> vIndex(G);
157  // assigning supply
158  Array<int> mcfSupply(n);
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
168  Array<int> mcfTail(m);
169  Array<int> mcfHead(m);
170  Array<int> mcfLb(m);
171  Array<int> mcfUb(m);
172  Array<TCost> mcfCost(m);
173  Array<int> mcfFlow(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 {
210  retCode = mcf(n, m - nSelfLoops, mcfSupply, mcfTail, mcfHead, mcfLb, mcfUb, mcfCost,
211  mcfFlow, mcfDual, &objVal);
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 
242 template<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
295 template<typename TCost>
296 void MinCostFlowReinelt<TCost>::beacircle(arctype** eplus, arctype** pre, bool* from_ub) {
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
408 template<typename TCost>
409 void MinCostFlowReinelt<TCost>::beadouble(arctype** eplus, arctype** pre, bool* from_ub) {
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
574 template<typename TCost>
575 int MinCostFlowReinelt<TCost>::mcf(int mcfNrNodes, int mcfNrArcs, Array<int>& supply,
576  Array<int>& mcfTail, Array<int>& mcfHead, Array<int>& mcfLb, Array<int>& mcfUb,
577  Array<TCost>& mcfCost, Array<int>& mcfFlow, Array<TCost>& mcfDual, TCost* mcfObj) {
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)
845  bool eplus_ori = s_orientation;
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 
855  arctype* s_arc_id = eminus;
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;
901  s_father = w_father;
902  s_orientation = w_orientation;
903  s_arc_id = w_arc_id;
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 }
ogdf
The namespace for all OGDF objects.
Definition: AugmentationModule.h:36
ogdf::MinCostFlowReinelt
Computes a min-cost flow using a network simplex method.
Definition: MinCostFlowReinelt.h:44
EpsilonTest.h
Compare floating point numbers with epsilons and integral numbers with normal compare operators.
ogdf::EpsilonTest
Definition: EpsilonTest.h:41
ogdf::MinCostFlowReinelt::MinCostFlowReinelt
MinCostFlowReinelt()
Definition: MinCostFlowReinelt.h:46
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:54
ogdf::MinCostFlowReinelt::last_n1
arctype * last_n1
Definition: MinCostFlowReinelt.h:119
ogdf::matching_blossom::infinity
TWeight infinity()
Helper function to get the maximum value for a given weight type.
Definition: utils.h:43
ogdf::MinCostFlowReinelt::startsearch
arctype * startsearch
Definition: MinCostFlowReinelt.h:125
ogdf::MinCostFlowReinelt::arctype::upper_bound
int upper_bound
Definition: MinCostFlowReinelt.h:95
ogdf::MinCostFlowReinelt::m_eps
EpsilonTest m_eps
Definition: MinCostFlowReinelt.h:110
ogdf::MinCostFlowReinelt::rootStruct
nodetype rootStruct
Definition: MinCostFlowReinelt.h:117
ogdf::MinCostFlowReinelt::nodetype::successor
nodetype * successor
Definition: MinCostFlowReinelt.h:80
ogdf::MinCostFlowReinelt::searchend_n1
arctype * searchend_n1
Definition: MinCostFlowReinelt.h:127
ogdf::MinCostFlowReinelt::nodetype::father
nodetype * father
Definition: MinCostFlowReinelt.h:79
ogdf::MinCostFlowReinelt::start_arc
arctype * start_arc
Definition: MinCostFlowReinelt.h:121
ogdf::MinCostFlowReinelt::nodetype::orientation
bool orientation
Definition: MinCostFlowReinelt.h:82
ogdf::MinCostFlowReinelt::call
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.
Definition: MinCostFlowReinelt.h:146
ogdf::MinCostFlowReinelt::nodetype::flow
int flow
Definition: MinCostFlowReinelt.h:84
ogdf::MinCostFlowReinelt::arctype::tail
nodetype * tail
Definition: MinCostFlowReinelt.h:92
ogdf::MinCostFlowReinelt::beadouble
void beadouble(arctype **eplus, arctype **pre, bool *from_ub)
Definition: MinCostFlowReinelt.h:409
ogdf::MinCostFlowReinelt::nodetype
Definition: MinCostFlowReinelt.h:78
ogdf::MinCostFlowReinelt::infinity
int infinity() const
Definition: MinCostFlowReinelt.h:73
OGDF_NEW_DELETE
#define OGDF_NEW_DELETE
Makes the class use OGDF's memory allocator.
Definition: memory.h:84
ogdf::MinCostFlowReinelt::nodetype::arc_id
arctype * arc_id
Definition: MinCostFlowReinelt.h:81
ogdf::MinCostFlowReinelt::start_b
arctype * start_b
Definition: MinCostFlowReinelt.h:122
ogdf::MinCostFlowReinelt::mcf
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)
Definition: MinCostFlowReinelt.h:575
ogdf::MinCostFlowReinelt::start_n1
arctype * start_n1
Definition: MinCostFlowReinelt.h:123
ogdf::MinCostFlowReinelt::searchend_n2
arctype * searchend_n2
Definition: MinCostFlowReinelt.h:128
ogdf::EdgeElement::isSelfLoop
bool isSelfLoop() const
Returns true iff the edge is a self-loop (source node = target node).
Definition: Graph_d.h:412
ogdf::MinCostFlowReinelt::arctype::head
nodetype * head
Definition: MinCostFlowReinelt.h:93
ogdf::Array< int >
ogdf::MinCostFlowModule
Interface for min-cost flow algorithms.
Definition: MinCostFlowModule.h:48
ogdf::MinCostFlowReinelt::arctype::cost
TCost cost
Definition: MinCostFlowReinelt.h:94
ogdf::MinCostFlowReinelt::start_n2
arctype * start_n2
Definition: MinCostFlowReinelt.h:124
ogdf::MinCostFlowReinelt::arctype
Definition: MinCostFlowReinelt.h:90
ogdf::MinCostFlowReinelt::nn
int nn
Definition: MinCostFlowReinelt.h:133
ogdf::EdgeElement::source
node source() const
Returns the source node of the edge.
Definition: Graph_d.h:391
ogdf::internal::GraphRegisteredArray
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition: Graph_d.h:651
ogdf::Graph
Data type for general directed graphs (adjacency list representation).
Definition: Graph_d.h:862
ogdf::MinCostFlowReinelt::beacircle
void beacircle(arctype **eplus, arctype **pre, bool *from_ub)
Definition: MinCostFlowReinelt.h:296
ogdf::MinCostFlowReinelt::mm
int mm
Definition: MinCostFlowReinelt.h:134
ogdf::MinCostFlowReinelt::m_maxCost
TCost m_maxCost
Definition: MinCostFlowReinelt.h:131
ogdf::MinCostFlowReinelt::searchend
arctype * searchend
Definition: MinCostFlowReinelt.h:126
ogdf::MinCostFlowReinelt::nodetype::nr_of_nodes
int nr_of_nodes
Definition: MinCostFlowReinelt.h:87
ogdf::MinCostFlowReinelt::arctype::next_arc
arctype * next_arc
Definition: MinCostFlowReinelt.h:91
ogdf::MinCostFlowReinelt::nodetype::dual
TCost dual
Definition: MinCostFlowReinelt.h:83
ogdf::MinCostFlowReinelt::root
nodetype * root
Definition: MinCostFlowReinelt.h:116
ogdf::MinCostFlowReinelt::start
void start(Array< int > &supply)
Definition: MinCostFlowReinelt.h:243
ogdf::MinCostFlowReinelt::arctype::arcnum
int arcnum
Definition: MinCostFlowReinelt.h:96
ogdf::EdgeElement
Class for the representation of edges.
Definition: Graph_d.h:356
ogdf::MinCostFlowReinelt::last_n2
arctype * last_n2
Definition: MinCostFlowReinelt.h:120
MinCostFlowModule.h
Definition of ogdf::MinCostFlowModule class template.
ogdf::MinCostFlowReinelt::nodetype::last
nodetype * last
Definition: MinCostFlowReinelt.h:86
ogdf::MinCostFlowReinelt::nodes
Array< nodetype > nodes
Definition: MinCostFlowReinelt.h:112
ogdf::EdgeElement::target
node target() const
Returns the target node of the edge.
Definition: Graph_d.h:394
ogdf::MinCostFlowReinelt::arcs
Array< arctype > arcs
Definition: MinCostFlowReinelt.h:113
ogdf::NodeElement
Class for the representation of nodes.
Definition: Graph_d.h:233
ogdf::MinCostFlowReinelt::nodetype::name
int name
Definition: MinCostFlowReinelt.h:85
ogdf::internal::EdgeArrayBase2
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition: Graph_d.h:709