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

Dual values of complex constraints wrong, poisons later dual values #337

Closed
ericphanson opened this issue Oct 13, 2019 · 1 comment · Fixed by #330
Closed

Dual values of complex constraints wrong, poisons later dual values #337

ericphanson opened this issue Oct 13, 2019 · 1 comment · Fixed by #330
Milestone

Comments

@ericphanson
Copy link
Collaborator

E.g.

using Convex, SCS, LinearAlgebra
solver = SCSSolver(verbose=0)
x = ComplexVariable(2, 2)
p = minimize( lambdamax(x), [ x[1,2] == im, x[2,2] == 1.0, x  - I(2) ] )
Convex.solve!(p, solver)

@show p.optval
@show p.constraints[1].dual
@show p.constraints[2].dual

using MATLAB
mat"""
cvx_begin sdp quiet
variable x(2, 2) complex hermitian
dual variable cvx_dual1
dual variable cvx_dual2
minimize( lambda_max(x) )
subject to
    cvx_dual1 : x(1,2) == j
    cvx_dual2 : x(2,2) == 1.0
    x >= -eye(2)
cvx_end
$(cvx_optval) = cvx_optval;
$(cvx_dual1) = cvx_dual1;
$(cvx_dual2) = cvx_dual2;
"""
@show cvx_optval
@show cvx_dual1
@show cvx_dual2;

yields

p.optval = 1.4999999802464283
(p.constraints[1]).dual = 5.587176841458554e-16
(p.constraints[2]).dual = 0.9999999500234388
cvx_optval = 1.4999999265147386
cvx_dual1 = 0.0 + 1.0000954705004044im
cvx_dual2 = 0.7499522176931694

Why? In

https://github.com/JuliaOpt/Convex.jl/blob/e0513acc7a2fa3c22325c7ea9e528b0a340f068b/src/solution.jl#L194-L214

the dual values are taken out of a big vector of dual values returned by MPB by using the constraint's size to determine the indexing. However, for complex dual values, they have been written as a long vector, and we only take the first half-- the real parts. Then the next dual value takes the next bit of the big vector of dual values, which is then can include the complex part of the previous dual value. So here, (p.constraints[1]).dual + im*(p.constraints[2]).dual is actually the true dual value for the first constraint (and hence matches cvx_dual1). And we've totally lost the dual value for the 2nd constraint (i.e. cvx_dual2).

I found this because MOI doesn't return a big vector of dual values, but instead returns the dual values for each constraint as you ask for it. Then when I ported the tests from #332 to the MOI branch (#330), I found I was missing a reshape in the MOI code. Adding the reshape added a size check, and I found MOI was returning double the number of values than the size expected (since it returns the real and complex parts). When I went to check how we handled this with MPB, I found that we did not, hence this issue.

This will be fixed with #330 (once I push some commits up), and I'll add this example as a test there.

@ericphanson
Copy link
Collaborator Author

Thanks to @ranocha for #332 which ended up surfacing this!

ericphanson added a commit to ericphanson/Convex.jl that referenced this issue Oct 13, 2019
ericphanson added a commit to ericphanson/Convex.jl that referenced this issue Oct 26, 2019
ericphanson added a commit to ericphanson/Convex.jl that referenced this issue Oct 28, 2019
@ericphanson ericphanson added this to the v0.13.0 milestone Nov 1, 2019
ericphanson added a commit to ericphanson/Convex.jl that referenced this issue Nov 27, 2019
ericphanson added a commit to ericphanson/Convex.jl that referenced this issue Dec 1, 2019
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.

1 participant