jump-dev / MathOptInterface.jl

A data structure for mathematical optimization problems
http://jump.dev/MathOptInterface.jl/
Other
392 stars 87 forks source link

Add Bridges.Constraint.ComplexNormInfinityToSecondOrderConeBridge #2451

Closed odow closed 6 months ago

odow commented 7 months ago

Basic

Tests

Documentation

Final touch

If the bridge depends on run-time values of other variables and constraints in the model:

x-ref #2450

Results in:

julia> using JuMP

julia> import SCS

julia> model = Model(SCS.Optimizer)
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: EMPTY_OPTIMIZER
Solver name: SCS

julia> @variable(model, x[1:2] in ComplexPlane())
2-element Vector{GenericAffExpr{ComplexF64, VariableRef}}:
 real(x[1]) + imag(x[1]) im
 real(x[2]) + imag(x[2]) im

julia> @variable(model, t)
t

julia> @objective(model, Min, t)
t

julia> @constraint(model, [i in 1:2], real(x[i]) >= i)
2-element Vector{ConstraintRef{Model, MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.GreaterThan{Float64}}, ScalarShape}}:
 real(x[1]) ≥ 1
 real(x[2]) ≥ 2

julia> @constraint(model, [i in 1:2], imag(x[i]) >= i + 1)
2-element Vector{ConstraintRef{Model, MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.GreaterThan{Float64}}, ScalarShape}}:
 imag(x[1]) ≥ 2
 imag(x[2]) ≥ 3

julia> @constraint(model, [t; x] in MOI.NormInfinityCone(3))
[t, real(x[1]) + imag(x[1]) im, real(x[2]) + imag(x[2]) im] ∈ MathOptInterface.NormInfinityCone(3)

julia> optimize!(model)
------------------------------------------------------------------
           SCS v3.2.4 - Splitting Conic Solver
    (c) Brendan O'Donoghue, Stanford University, 2012
------------------------------------------------------------------
problem:  variables n: 5, constraints m: 10
cones:    l: linear vars: 4
      q: soc vars: 6, qsize: 2
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): 10, nnz(P): 0
------------------------------------------------------------------
 iter | pri res | dua res |   gap   |   obj   |  scale  | time (s)
------------------------------------------------------------------
     0| 1.00e+01  1.00e+00  1.18e+01 -4.10e+00  1.00e-01  1.94e-04 
   100| 6.07e-05  1.07e-05  1.14e-04  3.61e+00  1.00e-01  3.24e-04 
------------------------------------------------------------------
status:  solved
timings: total: 3.29e-04s = setup: 1.54e-04s + solve: 1.76e-04s
     lin-sys: 4.47e-05s, cones: 2.32e-05s, accel: 9.87e-06s
------------------------------------------------------------------
objective = 3.605664
------------------------------------------------------------------

julia> value.(x)
2-element Vector{ComplexF64}:
 1.2337017750444443 + 2.4674035500888887im
 2.0000404815637665 + 3.0000607223456446im

julia> abs.(value.(x))
2-element Vector{Float64}:
 2.758641032961531
 3.6056242546409205

julia> maximum(abs.(value.(x)))
3.6056242546409205

julia> value(t)
3.6057206297182596
odow commented 6 months ago

I'm going to wait until after #2471 is merged so that this can go into v1.28.0. There's no rush for it.

odow commented 6 months ago

Actually the release is getting larger, so let's just bundle it all in.