-
Couldn't load subscription status.
- Fork 122
Description
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.7499522176931694Why? In
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.