Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Starting values and Objective.SlackBridge #3270

Closed
blegat opened this issue Mar 7, 2023 · 2 comments · Fixed by #3422
Closed

Starting values and Objective.SlackBridge #3270

blegat opened this issue Mar 7, 2023 · 2 comments · Fixed by #3422

Comments

@blegat
Copy link
Member

blegat commented Mar 7, 2023

While working on jump-dev/DiffOpt.jl#231, I found out that there might be some unexpected behavior to

julia> using SCS, JuMP

julia> model = Model(SCS.Optimizer);

julia> @variable(model, x);

julia> @objective(model, Min, x^2);

julia> optimize!(model)
------------------------------------------------------------------
	       SCS v3.2.1 - Splitting Conic Solver
	(c) Brendan O'Donoghue, Stanford University, 2012
------------------------------------------------------------------
problem:  variables n: 2, constraints m: 3
cones: 	  q: soc vars: 3, qsize: 1
settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07
	  alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1
	  max_iters: 100000, normalize: 1, rho_x: 1.00e-06
	  acceleration_lookback: 10, acceleration_interval: 10
lin-sys:  sparse-direct-amd-qdldl
	  nnz(A): 3, nnz(P): 0
------------------------------------------------------------------
 iter | pri res | dua res |   gap   |   obj   |  scale  | time (s)
------------------------------------------------------------------
     0| 2.07e+01  1.00e+00  2.83e+01 -1.41e+01  1.00e-01  1.37e-03 
    25| 1.14e-05  2.44e-08  1.61e-05  8.04e-06  1.00e-01  1.39e-03 
------------------------------------------------------------------
status:  solved
timings: total: 1.39e-03s = setup: 1.35e-03s + solve: 4.27e-05s
	 lin-sys: 3.43e-06s, cones: 2.57e-06s, accel: 7.72e-07s
------------------------------------------------------------------
objective = 0.000008
------------------------------------------------------------------

julia> set_start_values(model)

julia> model.moi_backend.optimizer.model.model_cache.varattr
Dict{MathOptInterface.AbstractVariableAttribute, Dict{MathOptInterface.VariableIndex, Any}} with 1 entry:
  VariablePrimalStart() => Dict(VariableIndex(1)=>0.0)

julia> model.moi_backend.optimizer.model.model_cache.conattr
Dict{MathOptInterface.AbstractConstraintAttribute, Dict{MathOptInterface.ConstraintIndex, Any}}()

julia> optimize!(model)
------------------------------------------------------------------
	       SCS v3.2.1 - Splitting Conic Solver
	(c) Brendan O'Donoghue, Stanford University, 2012
------------------------------------------------------------------
problem:  variables n: 2, constraints m: 3
cones: 	  q: soc vars: 3, qsize: 1
settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07
	  alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1
	  max_iters: 100000, normalize: 1, rho_x: 1.00e-06
	  acceleration_lookback: 10, acceleration_interval: 10
lin-sys:  sparse-direct-amd-qdldl
	  nnz(A): 3, nnz(P): 0
------------------------------------------------------------------
 iter | pri res | dua res |   gap   |   obj   |  scale  | time (s)
------------------------------------------------------------------
     0| 2.07e+01  1.00e+00  2.83e+01 -1.41e+01  1.00e-01  5.49e-05 
    25| 1.14e-05  2.44e-08  1.61e-05  8.04e-06  1.00e-01  6.44e-05 
------------------------------------------------------------------
status:  solved
timings: total: 6.53e-05s = setup: 4.19e-05s + solve: 2.34e-05s
	 lin-sys: 2.26e-06s, cones: 2.09e-06s, accel: 6.02e-07s
------------------------------------------------------------------
objective = 0.000008
------------------------------------------------------------------

We can see that while the starting value is set for the variable, it is not set for the constraint. So SCS starts from scratch.
Indeed, the objective is bridges with Objective.SlackBridge and then Constraint.QuadtoSOC into a RotatedSecondOrderCone constraint that SCS supports.
However, no ConstraintDualStart or ConstraintPrimalStart will be set to this constraint by set_start_values!
What should be done is to set a ConstraintDualStart of -1.0 to and a ConstraintPrimalStart of 0.0 to the quadratic constraint.
These should get transformed into the correct dual and primal starting values of the RotatedSecondOrderCone using the values of the VariablePrimalStart.

I have experimented with a way to fix it in the copy_dual.jl file of jump-dev/DiffOpt.jl#231
The idea is to define new attributes that serve as objective dual and primal starting values.
The objective dual starting values kind of make sense.
In the lagrangian, we have objective - sum dual * constraint_primal. So if the dual of the objective was -1, we would just have - sum dual * ... with no special case. So the dual of the objective is no too shocking so I called it ObjectiveDualStart.
For the primal start it's doesn't make much sense outside of the context of the slack bridge so I called it ObjectiveSlackGapPrimalStart.
When they are set to any ModelLike, they are ignored by default unless it's CachingOptimizer which passes it down to the optimizer or AbstractBridgeOptimizer which passes it to the objective bridge.

I think we should add this to MOI and use it from JuMP.set_start_values(model)

@odow
Copy link
Member

odow commented Apr 10, 2023

@blegat what's the status of this?

@blegat
Copy link
Member Author

blegat commented Apr 11, 2023

My suggestion in #3271 is to add attributes in the MOI Bridges submodule and to set them from the JuMP set_start_value function

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

2 participants