@@ -61,7 +61,7 @@ cdef class CVXOPTSDPBackend(GenericSDPBackend):
61
61
" reltol" :1e-6 ,
62
62
" feastol" :1e-7 ,
63
63
" refinement" :0 }
64
-
64
+ self .answer = {}
65
65
if maximization:
66
66
self .set_sense(+ 1 )
67
67
else :
@@ -255,8 +255,8 @@ cdef class CVXOPTSDPBackend(GenericSDPBackend):
255
255
INPUT:
256
256
257
257
- ``coefficients`` an iterable with ``(c,v)`` pairs where ``c``
258
- is a variable index (integer) and ``v`` is a value (real
259
- value). The pairs come sorted by indices. If c is -1 it
258
+ is a variable index (integer) and ``v`` is a value (matrix).
259
+ The pairs come sorted by indices. If c is -1 it
260
260
represents the constant coefficient.
261
261
262
262
- ``name`` - an optional name for this row (default: ``None``)
@@ -435,8 +435,6 @@ cdef class CVXOPTSDPBackend(GenericSDPBackend):
435
435
436
436
EXAMPLE::
437
437
438
- sage: from sage.numerical.backends.generic_sdp_backend import get_solver
439
- sage: p = get_solver(solver = "cvxopt")
440
438
sage: p = SemidefiniteProgram(solver = "cvxopt", maximization=False)
441
439
sage: x = p.new_variable()
442
440
sage: p.set_objective(x[0] - x[1] + x[2])
@@ -462,6 +460,32 @@ cdef class CVXOPTSDPBackend(GenericSDPBackend):
462
460
i+= 1
463
461
return sum
464
462
463
+ cpdef _get_answer(self ):
464
+ """
465
+ return the complete output dict of the solver
466
+
467
+ Mainly for testing purposes
468
+
469
+ TESTS::
470
+
471
+ sage: p = SemidefiniteProgram(maximization = False, solver='cvxopt')
472
+ sage: x = p.new_variable()
473
+ sage: p.set_objective(x[0] - x[1])
474
+ sage: a1 = matrix([[1, 2.], [2., 3.]])
475
+ sage: a2 = matrix([[3, 4.], [4., 5.]])
476
+ sage: a3 = matrix([[5, 6.], [6., 7.]])
477
+ sage: b1 = matrix([[1, 1.], [1., 1.]])
478
+ sage: b2 = matrix([[2, 2.], [2., 2.]])
479
+ sage: b3 = matrix([[3, 3.], [3., 3.]])
480
+ sage: p.add_constraint(a1*x[0] + a2*x[1] <= a3)
481
+ sage: p.add_constraint(b1*x[0] + b2*x[1] <= b3)
482
+ sage: p.solve(); # tol 1e-08
483
+ -3.0
484
+ sage: p.get_backend()._get_answer()
485
+ {...}
486
+ """
487
+ return self .answer
488
+
465
489
cpdef get_variable_value(self , int variable):
466
490
"""
467
491
Return the value of a variable given by the solver.
@@ -617,8 +641,108 @@ cdef class CVXOPTSDPBackend(GenericSDPBackend):
617
641
matrices.append(m)
618
642
return (indices, matrices)
619
643
644
+ cpdef dual_variable(self , int i, sparse = False ):
645
+ """
646
+ The `i`-th dual variable
647
+
648
+ Available after self.solve() is called, otherwise the result is undefined
649
+
650
+ - ``index`` (integer) -- the constraint's id.
651
+
652
+ OUTPUT:
653
+
654
+ The matrix of the `i`-th dual variable
655
+
656
+ EXAMPLE::
657
+
658
+ sage: p = SemidefiniteProgram(maximization = False, solver='cvxopt')
659
+ sage: x = p.new_variable()
660
+ sage: p.set_objective(x[0] - x[1])
661
+ sage: a1 = matrix([[1, 2.], [2., 3.]])
662
+ sage: a2 = matrix([[3, 4.], [4., 5.]])
663
+ sage: a3 = matrix([[5, 6.], [6., 7.]])
664
+ sage: b1 = matrix([[1, 1.], [1., 1.]])
665
+ sage: b2 = matrix([[2, 2.], [2., 2.]])
666
+ sage: b3 = matrix([[3, 3.], [3., 3.]])
667
+ sage: p.add_constraint(a1*x[0] + a2*x[1] <= a3)
668
+ sage: p.add_constraint(b1*x[0] + b2*x[1] <= b3)
669
+ sage: p.solve() # tol 1e-08
670
+ -3.0
671
+ sage: B=p.get_backend()
672
+ sage: x=p.get_values(x).values()
673
+ sage: -(a3*B.dual_variable(0)).trace()-(b3*B.dual_variable(1)).trace() # tol 1e-07
674
+ -3.0
675
+ sage: g = sum((B.slack(j)*B.dual_variable(j)).trace() for j in range(2)); g # tol 1.5e-08
676
+ 0.0
677
+
678
+
679
+ TESTS::
680
+
681
+ sage: B.dual_variable(7)
682
+ ...
683
+ Traceback (most recent call last):
684
+ ...
685
+ IndexError: list index out of range
686
+ sage: abs(g - B._get_answer()['gap']) # tol 1e-22
687
+ 0.0
688
+
689
+ """
690
+ cdef int n
691
+ n = self .answer[' zs' ][i].size[0 ]
692
+ assert (n == self .answer[' zs' ][i].size[1 ]) # must be square matrix
693
+ return Matrix(n, n, list (self .answer[' zs' ][i]), sparse = sparse)
694
+
695
+ cpdef slack(self , int i, sparse = False ):
696
+ """
697
+ Slack of the `i`-th constraint
698
+
699
+ Available after self.solve() is called, otherwise the result is undefined
700
+
701
+ - ``index`` (integer) -- the constraint's id.
702
+
703
+ OUTPUT:
704
+
705
+ The matrix of the slack of the `i`-th constraint
706
+
707
+ EXAMPLE::
708
+
709
+ sage: p = SemidefiniteProgram(maximization = False, solver='cvxopt')
710
+ sage: x = p.new_variable()
711
+ sage: p.set_objective(x[0] - x[1])
712
+ sage: a1 = matrix([[1, 2.], [2., 3.]])
713
+ sage: a2 = matrix([[3, 4.], [4., 5.]])
714
+ sage: a3 = matrix([[5, 6.], [6., 7.]])
715
+ sage: b1 = matrix([[1, 1.], [1., 1.]])
716
+ sage: b2 = matrix([[2, 2.], [2., 2.]])
717
+ sage: b3 = matrix([[3, 3.], [3., 3.]])
718
+ sage: p.add_constraint(a1*x[0] + a2*x[1] <= a3)
719
+ sage: p.add_constraint(b1*x[0] + b2*x[1] <= b3)
720
+ sage: p.solve() # tol 1e-08
721
+ -3.0
722
+ sage: B = p.get_backend()
723
+ sage: B1 = B.slack(1); B1 # tol 1e-08
724
+ [0.0 0.0]
725
+ [0.0 0.0]
726
+ sage: B1.is_positive_definite()
727
+ True
728
+ sage: x = p.get_values(x).values()
729
+ sage: x[0]*b1 + x[1]*b2 - b3 + B1 # tol 1e-09
730
+ [0.0 0.0]
731
+ [0.0 0.0]
732
+
733
+ TESTS::
620
734
735
+ sage: B.slack(7)
736
+ ...
737
+ Traceback (most recent call last):
738
+ ...
739
+ IndexError: list index out of range
621
740
741
+ """
742
+ cdef int n
743
+ n = self .answer[' ss' ][i].size[0 ]
744
+ assert (n == self .answer[' ss' ][i].size[1 ]) # must be square matrix
745
+ return Matrix(n, n, list (self .answer[' ss' ][i]), sparse = sparse)
622
746
623
747
cpdef row_name(self , int index):
624
748
"""
0 commit comments