ucd-cws/calvin

Piecewise link upper bound

Closed this issue · 4 comments

We currently do not explicitly impose a physical upper bound on the piecewise (economically-represented) links.

I do not think this is a problem, because the physical upper bound is used by Justin's matrix export code to divide up the pieces. In other words, as long as the sum of the upper bounds of the piecewise pieces is equal to the physical upper bound, we should be ok.

Say we have one link with bounds [0,100]. If we divide this into 4 pieces, they all have bounds [0,25], there is no danger of exceeding the physical upper bound of 100.

BUT, we may be picking the wrong dual values for these links. We currently choose the maximum one among the pieces. But should it be the last one instead?

Reason: we only want the dual on the PHYSICAL upper bound. The other ones are meaningless.

I'm putting this here just so we have a record of the conversation. But if we agree that this should be changed, I will assign myself to fix postprocess.py.

@jdherman my suggestion would be that before adding new constraints to the model structure, one at a time for a few constraints (or more) relax it by one unit, and look at how much it changes the objective and compare it to what we are thinking the dual would be (min, max dual, or dual on the last piece). If they are different, then yes, we have to add a new constraint for links (not arcs :))

I set up a test network in pyomo that has 1 "reservoir" and one piecewise demand node ("A").

set N := 
SOURCE
SINK
INITIAL
FINAL
A
S;

set k := 0 1 2 3 4 5;

param source := SOURCE; 
param sink := SINK;

param: A: c a l u :=
SOURCE  INITIAL 0   0   1   0   10000000
INITIAL S   0   0   1   45 45
S A 0 -10.0 1 0 10
S A 1 -9.0 1 0 10
S A 2 -8.0 1 0 10
S A 3 -7.0 1 0 10
S A 4 -6.0 1 0 10
S FINAL 0 0 1 0 10000000
A FINAL 0 0 1 0 10000000
FINAL   SINK    0   0   1   0   10000000;

A couple of observations:

  • The maximum flow to the piecewise pieces adds up to 50. So the total flow will never exceed 50; the physical upper bound is respected.
  • If the amount of available water (fixed flow from INITIAL to S) is less than 50, the pieces are filled in order of their cost, as expected:
"X[INITIAL,S,0]": {
                    "Value": 45.0
                },
                "X[S,A,0]": {
                    "Value": 10.0
                },
                "X[S,A,1]": {
                    "Value": 10.0
                },
                "X[S,A,2]": {
                    "Value": 10.0
                },
                "X[S,A,3]": {
                    "Value": 10.0
                },
                "X[S,A,4]": {
                    "Value": 5.0
                },

The last piece is not full, so it is not a binding constraint, and its dual value is zero (zero values are not reported in the pyomo output). The dual associated with the physical upper bound should also be zero in this case, because there is no value in increasing the capacity of the last piece. Using the maximum dual value, as I did before, is wrong.

  • If the amount of available water is greater than or equal to 50, then all of the pieces are filled. In this case the dual value on the last piece is equal to its unit cost (-6.0). This may be different in a more complicated network, but the point is it's not zero. This was what confused us before, I think, because here the "last" and "maximum" options are the same!

So, I will change the postprocessor to get the last dual value for piecewise links rather than the maximum one. But this isn't urgent, I'll wait until Max has the chance to make his changes first. We can work on it later next week sometime.

I didn't close this issue. I don't know how it got closed :) Please open it if you think it is unsolved.

It must have closed automatically when you merged the pull request. Thanks!

It should be ok to leave it closed, I think we fixed the issue with the duals. We'll find out as we analyze the data.