plasmo-dev / Plasmo.jl

A Platform for Scalable Modeling and Optimization
Other
143 stars 20 forks source link

`dual` does not work on linkconstraints set after `optimize!` is called #97

Open dlcole3 opened 9 months ago

dlcole3 commented 9 months ago

Plasmo throws an error if you try to query the dual of a link constraint that was added after optimize! was called once. A MWE is included below. If I call optimize! on a graph and then add a link constraint to the graph, then call optimize! again and try to query the dual of the link constraint I added, I get an error. This is on Plasmo v0.5.4.

using Plasmo, HiGHS
g = OptiGraph()
set_optimizer(g, HiGHS.Optimizer)

@optinode(g, n1)
@optinode(g, n2)

@variable(n1, x[1:2] >= 0)
@variable(n2, x[1:2] >= 0)

lc = @linkconstraint(g, [i = 1:2], n1[:x][i] == n2[:x][i])

@objective(n1, Min, n1[:x][1])

optimize!(g)

dual.(lc)

lc_new = @linkconstraint(g, n1[:x][1] >= n2[:x][2])

optimize!(g)

dual(lc_new)

This is a pretty minor error (I ran into this trying to implement a decomposition scheme). The stacktrace points to this line, so I don't think the EdgePointer object is being properly updated after optimize! has been called once.

jalving commented 9 months ago

Thanks for reporting. Yes, i bet it is failing to track the new constraint once it has a solution. This should (hopefully) be a straight-forward fix.

dlcole3 commented 7 months ago

@jalving I think this is the same problem, but thought I would pass on an extra example I ran into (took me a while to realize it was probably stemming from this same problem above). I have found that after calling optimize!, any additional link constraints are not recognized by the optimizer. In the example below, you have to call reset_optimizer(g0) before the new link constraint is enforced in the optimization.

using Plasmo, HiGHS, JuMP

g0 = OptiGraph()

@optinode(g0, node1)
@variable(node1, x1 >= 0)
@objective(node1, Min, x1)

@optinode(g0, node2)
@variable(node2, x2 >= 0)
@objective(node2, Min, x2)

@linkconstraint(g0, g0[:node1][:x1] + g0[:node2][:x2] >= 1)

@linkconstraint(g0, g0[:node1][:x1] + g0[:node2][:x2] >= 2)

set_optimizer(g0, HiGHS.Optimizer)

optimize!(g0)
println(objective_value(g0))

@linkconstraint(g0, g0[:node2][:x2] + g0[:node1][:x1] >= 3)

optimize!(g0)

println(objective_value(g0)) # Objective value should be 3, but it equals 2

MOIU.reset_optimizer(g0)
optimize!(g0)
println(objective_value(g0)) # Objective value now equals 3