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

Revisit PR#2508 #2513

Closed
odow opened this issue Jun 13, 2024 · 5 comments · Fixed by #2515
Closed

Revisit PR#2508 #2513

odow opened this issue Jun 13, 2024 · 5 comments · Fixed by #2515

Comments

@odow
Copy link
Member

odow commented Jun 13, 2024

See https://github.com/jump-dev/MathOptInterface.jl/actions/runs/9491359380/job/26156620575

Likely caused by #2508

Found working on #2495

@odow
Copy link
Member Author

odow commented Jun 13, 2024

#2508 is wrong, because they are not the same duals:

import CSDP
import MathOptInterface as MOI
function main()
    model = MOI.instantiate(CSDP.Optimizer, with_bridge_type = Float64)
    MOI.Bridges.remove_bridge(model, MOI.Bridges.Variable.ZerosBridge{Float64})
    config = MOI.Test.Config(; rtol = 1e-3, atol = 1e-3)
    MOI.Test.test_conic_PositiveSemidefiniteConeTriangle_VectorOfVariables(model, config)
    return model
end
model = main()
julia> model = main()
CSDP 6.2.0
Iter:  0 Ap: 0.00e+00 Pobj:  0.0000000e+00 Ad: 0.00e+00 Dobj:  0.0000000e+00 
Iter:  1 Ap: 1.00e+00 Pobj: -1.3091666e+01 Ad: 9.00e-01 Dobj: -1.4400002e+00 
Iter:  2 Ap: 1.00e+00 Pobj: -6.5001984e+00 Ad: 9.15e-01 Dobj: -8.2898589e-01 
Iter:  3 Ap: 9.50e-01 Pobj: -2.1617676e+00 Ad: 8.66e-01 Dobj: -1.4438101e+00 
Iter:  4 Ap: 1.00e+00 Pobj: -2.0165778e+00 Ad: 9.38e-01 Dobj: -1.9577837e+00 
Iter:  5 Ap: 1.00e+00 Pobj: -2.0005894e+00 Ad: 9.66e-01 Dobj: -1.9980351e+00 
Iter:  6 Ap: 1.00e+00 Pobj: -2.0000291e+00 Ad: 9.82e-01 Dobj: -1.9999373e+00 
Iter:  7 Ap: 1.00e+00 Pobj: -2.0000041e+00 Ad: 1.00e+00 Dobj: -1.9999974e+00 
Iter:  8 Ap: 1.00e+00 Pobj: -2.0000009e+00 Ad: 1.00e+00 Dobj: -2.0000001e+00 
Iter:  9 Ap: 1.00e+00 Pobj: -2.0000001e+00 Ad: 1.00e+00 Dobj: -2.0000000e+00 
Iter: 10 Ap: 9.70e-01 Pobj: -2.0000000e+00 Ad: 9.70e-01 Dobj: -2.0000000e+00 
Success: SDP solved
Primal objective value: -2.0000000e+00 
Dual objective value: -2.0000000e+00 
Relative primal infeasibility: 2.72e-16 
Relative dual infeasibility: 2.12e-09 
Real Relative Gap: -2.72e-10 
XZ Relative Gap: 6.89e-09 
DIMACS error measures: 2.72e-16 0.00e+00 4.34e-09 0.00e+00 -2.72e-10 6.89e-09
MOI.get(model, a, bridge.slack_in_set) = [1.0000000029485168, -1.0000000016370894, 1.0000000029485168]
MOI.get(model, a, bridge.equality) = [1.000000000703211, -2.0000000032741787, 1.000000000703211]
Test Failed at /Users/oscar/.julia/dev/MathOptInterface/src/Test/test_conic.jl:4857
  Expression: (MOI.get(model, MOI.ConstraintDual(), cX), cXv, atol = atol, rtol = rtol)
   Evaluated: [1.000000000703211, -2.0000000032741787, 1.000000000703211]  [1.0, -1.0, 1.0] (atol=0.001, rtol=0.001)

@odow
Copy link
Member Author

odow commented Jun 13, 2024

julia> function main2()
           model = MOI.instantiate(CSDP.Optimizer, with_bridge_type = Float64)
           MOI.set(model, MOI.Silent(), true)
           x, _ = MOI.add_constrained_variables(model, MOI.Nonnegatives(2))
           g = MOI.Utilities.operate(vcat, Float64, 1.0 * x[1], 1.0, 1.0 * x[2])
           ci = MOI.add_constraint(model, g, MOI.PositiveSemidefiniteConeTriangle(2))
           MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
           f = 1.0 * x[1] + 1.0 * x[2]
           MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f)
           MOI.optimize!(model)
           dual = MOI.get(model, MOI.ConstraintDual(), ci)
           return model, dual
       end
main2 (generic function with 1 method)

julia> model, dual = main2();
MOI.get(model, a, bridge.slack_in_set) = [1.0000000200504315, -1.000000020050426, 1.0000000200504315]
MOI.get(model, a, bridge.equality) = [1.0000000100252102, -2.000000040100852, 1.0000000100252102]

julia> dual
3-element Vector{Float64}:
  1.0000000100252102
 -2.000000040100852
  1.0000000100252102

julia> model
MOIB.LazyBridgeOptimizer{MOIU.CachingOptimizer{CSDP.Optimizer, MOIU.UniversalFallback{MOIU.Model{Float64}}}}
├ Variable bridges: none
├ Constraint bridges:
│ ├ MOIB.Constraint.ScalarizeBridge{Float64, MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64}}
│ └ MOIB.Constraint.VectorSlackBridge{Float64, MOI.VectorAffineFunction{Float64}, MOI.PositiveSemidefiniteConeTriangle}
├ Objective bridges: none
└ model: MOIU.CachingOptimizer
  ├ state: ATTACHED_OPTIMIZER
  ├ mode: AUTOMATIC
  ├ model_cache: MOIU.UniversalFallback{MOIU.Model{Float64}}
  │ ├ ObjectiveSense: MIN_SENSE
  │ ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64}
  │ ├ NumberOfVariables: 5
  │ └ NumberOfConstraints: 5
  │   ├ MOI.ScalarAffineFunction{Float64} in MOI.EqualTo{Float64}: 3
  │   ├ MOI.VectorOfVariables in MOI.Nonnegatives: 1
  │   └ MOI.VectorOfVariables in MOI.PositiveSemidefiniteConeTriangle: 1
  └ optimizer: CSDP.Optimizer
    ├ ObjectiveSense: unknown
    ├ ObjectiveFunctionType: unknown
    ├ NumberOfVariables: unknown
    └ NumberOfConstraints: unknown

@odow odow changed the title solver-test failures getting dual of PSD constraints Revisit PR#2508 Jun 13, 2024
@odow
Copy link
Member Author

odow commented Jun 13, 2024

I've reverted #2508 for now, but @blegat probably wants to take another look at a proper fix.

@blegat
Copy link
Member

blegat commented Jun 13, 2024

It makes sense, because the constraint is VectorAffineFunction-in-S and we transform to VectorAffineFunction-in-Zeros, if the scalar product between S and Zeros is not the same, we should scale the dual.

@odow
Copy link
Member Author

odow commented Jun 13, 2024

How do we find the arbitrary scaling though?

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