[Lemon-user] Network Simplex Initialisation (based on Bonneel's network_simplex_simple.h)

Kovács Péter kpeter at inf.elte.hu
Sun May 24 16:43:03 CEST 2015


Hi Matthew,

I did not know about Bonneel's version of our code, but I'm glad to see 
such use cases as well.

Your approach for utilizing an initial flow is interesting, but I think 
some problems may arise and this implementation seems to be incorrect 
for me.

Let me note some issues without completeness:
   * The invariant of the network simplex algorithm requires that for 
each arc outside the current spanning tree, the flow value must be 
either at the lower bound or at the upper bound. If 
delta>initialValues_[i][j], then your code decreases the delta value and 
performs a non-saturating flow augmentation. It means that if delta>0, 
none of the arcs along the considered cycle will meet the above 
conditions, so none of them can be selected to be the leaving arc 
without violating the invariant.
   * If delta==initialValues_[i][j], then your code explicitly 
overwrites the change variable to false, but the leaving arc may not be 
same as the entering arc (if another arc is also saturated).
   * Are you sure that delta<initialValues_[i][j] case cannot occur?


 > I have tried initialising it to the optimal solution, and I still get
 > iterations in the while loop of the execution (i.e.
 > pivot.findEnteringArc() is true and change is true) and I can't quite
 > figure out why.

There can be different reasons for this:
   * maybe the "guided" iterations were performed incorrectly (see above)
   * or you observed so-called degenerate iterations in the while loop

Degeneracy is a well-known phenomenon in simplex methods. It is possible 
that a pivot step actually finds a cycle of zero residual capacity (i.e. 
delta == 0), and hence the flow cost cannot be decreased, only the 
spanning tree is modi
ed. You can easily check this by checking the 
value of the delta variable in these iterations. If you encounter 
positive delta values in the while loop, then something is surely wrong 
(either the flow was not optimal or the algorithm is incorrect).


Anyway, why is it important for you to start the algorithm with initial 
flow values? Merely for efficiency reasons? Maybe the algorithm is 
efficient enough without such guidance. Have you tried it?


If it is really important to consider the initial flow values, let me 
suggest an entirely different approach. You can transform the input of 
the algorithm, rather than the algorithm itself, which is an easier and 
safer way. For each arc e=(i,j) having d=initialValues_[i][j] > 0,
   * decrease the capacity of e with d
   * add a reverse arc e'=(j,i) to the graph with capacity d and cost 
equal to -cost[i][j]
Furthermore (assuming that the initial flow was feasible), set the 
supply/demand values to zero for each node.

If you find an optimal flow x in this modified graph and sum it with 
your initial flow, then you will get an optimal flow in the original 
graph. (The flow value for an arc e in the original graph should be set 
to initialValue[e] + x[e] - x[e'].)


I hope these thoughts help.


Best regards,
Péter




> Hello,
>
> I am basing myself on the network_simplex_simple.h code written by N.
> Bonneel (http://liris.cnrs.fr/~nbonneel/FastTransport/).
>
> I am developing an algorithm where I would need to initialise the
> network with already known flows.
> I want to input a 2D array of size (number of sources x number of sinks)
> and the network simplex to begin the algorithm with the flows in my 2D
> array.
>
> First, is there something similar already coded?
>
> If not, I gave it a try and here is what I did :
>
> My idea was to let the algorithm initialise the artificial arcs with the
> root, and before it runs the main execution loop, I do iterations where
> I set the entering arc and the amount by which the flow changes.
>
> initialValues_[i][j] : 2D array with initial flows with n0_ sources and
> n1_ sinks
>
> // EDIT IN THE START() FUNCTION
>
> template <typename PivotRuleImpl>
>          ProblemType start() {
>
> // BEGIN EDIT
>
>              // Initialisation by user sets the entering arc and the
> quantity by which the flow changes.
>              // The rest is handled by already existing functions.
>
>              if(my_initialise_bool){
>                for(int i = 0; i < n0_; i++) {
>                  for(int j = 0; j < n1_; j++) {
>                  if(initialValues_[i][j]>0){
>
> in_arc=findArc(_graph.nodeFromId(i),_graph.nodeFromId(j+n0_));
>                    // sanity check :  i = _node_id(_source[in_arc]) and
> j = _node_id(_target[in_arc]) --> returns true! yay! :)
>                    findJoinNode();
>                    bool change = findLeavingArc();
>                    if (delta >= LEMON_MAX) return UNBOUNDED;
>
>                    // if the amount of flow I want to initialise with is
> lower the total possible amount, then change = false
>                    if(delta>initialValues_[i][j]){
>                      change = false;
>                    } else {
>                      change = true;
>                    }
>
>                    // set delta = amount of flow I want to initialise with
>                    delta = (double)initialValues_[i][j];
>
>                    changeFlow(change);
>                    if (change) {
>                        updateTreeStructure();
>                        updatePotential();
>                    }
>                  }
>                  }
>                }
>              }
>
> // END EDIT
>
>              PivotRuleImpl pivot(*this);
>
>              if (!initialPivots()) return UNBOUNDED;
>
>              // Execute the Network Simplex algorithm
>              while (pivot.findEnteringArc()) {
>                  findJoinNode();
>                  bool change = findLeavingArc();
>                  if (delta >= LEMON_MAX) return UNBOUNDED;
>                  changeFlow(change);
>                  if (change) {
>                      updateTreeStructure();
>                      updatePotential();
>                  }   [...]
>
>
> After my "edit", I get that the artificial arcs have 0 flow (which is
> normal).
>
> I have tried initialising it to the optimal solution, and I still get
> iterations in the while loop of the execution (i.e.
> pivot.findEnteringArc() is true and change is true) and I can't quite
> figure out why.
>
> If anyone knows the solution or has any appropriate direction of
> inquiry, it would be much appreciated!
>
> Cheers,
>
> Matthew
>
>
> _______________________________________________
> Lemon-user mailing list
> Lemon-user at lemon.cs.elte.hu
> http://lemon.cs.elte.hu/mailman/listinfo/lemon-user
>



More information about the Lemon-user mailing list