33# Use of this source code is governed by an MIT-style license that can be found
44# in the LICENSE.md file or at https://opensource.org/licenses/MIT.
55
6- import MathOptInterface as MOI
6+ macro check (expr)
7+ @assert expr. head == :call
8+ msg = " Error calling $(expr. args[1 ]) "
9+ return quote
10+ if (ret = $ (esc (expr))) != 0
11+ error ($ msg)
12+ end
13+ end
14+ end
715
816mutable struct Optimizer <: MOI.AbstractOptimizer
917 dsdp:: Ptr{Cvoid}
6371
6472varmap (optimizer:: Optimizer , vi:: MOI.VariableIndex ) = optimizer. varmap[vi. value]
6573
74+ # MOI.Silent
75+
6676MOI. supports (:: Optimizer , :: MOI.Silent ) = true
6777
6878function MOI. set (optimizer:: Optimizer , :: MOI.Silent , value:: Bool )
7282
7383MOI. get (optimizer:: Optimizer , :: MOI.Silent ) = optimizer. silent
7484
85+ # MOI.SolverName
86+
7587MOI. get (:: Optimizer , :: MOI.SolverName ) = " DSDP"
7688
7789function MOI. empty! (optimizer:: Optimizer )
@@ -182,13 +194,13 @@ for (param, default) in gettable_options
182194 struct $ param <: GettableOption end
183195 function _call_get (dsdp, :: $param )
184196 ret = Ref {$T} ()
185- $ getter (dsdp, ret)
197+ @check $ getter (dsdp, ret)
186198 return ret[]
187199 end
188200 options_setters[$ sym] = $ setter
189201 _dict_set! (options, :: $param , val) = options[$ sym] = val
190202 _dict_get (options, :: $param ) = get (options, $ sym, $ default)
191- _call_set! (dsdp, :: $param , val) = $ setter (dsdp, val)
203+ _call_set! (dsdp, :: $param , val) = @check $ setter (dsdp, val)
192204 end
193205end
194206
@@ -200,7 +212,7 @@ for (param, default) in options
200212 options_setters[$ sym] = $ setter
201213 _dict_set! (options, :: $param , val) = options[$ sym] = val
202214 _dict_get (options, :: $param ) = get (options, $ sym, $ default)
203- _call_set! (dsdp, :: $param , val) = $ setter (dsdp, val)
215+ _call_set! (dsdp, :: $param , val) = @check $ setter (dsdp, val)
204216 end
205217end
206218
@@ -421,14 +433,14 @@ function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike)
421433 dest. lpdrows = Int[]
422434 dest. lpcoefs = Cdouble[]
423435 p = Ref {Ptr{Cvoid}} ()
424- DSDPCreate (length (dest. b), p)
436+ @check DSDPCreate (length (dest. b), p)
425437 dest. dsdp = p[]
426438 for (option, value) in dest. options
427439 options_setters[option](dest. dsdp, value)
428440 end
429441 if ! iszero (num_sdp)
430442 sdpcone = Ref {Ptr{Cvoid}} ()
431- DSDPCreateSDPCone (dest. dsdp, num_sdp, sdpcone)
443+ @check DSDPCreateSDPCone (dest. dsdp, num_sdp, sdpcone)
432444 dest. sdpcone = sdpcone[]
433445 for i in eachindex (dest. blockdims)
434446 if dest. blockdims[i] < 0
@@ -444,7 +456,7 @@ function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike)
444456 for constr in eachindex (dest. b)
445457 # TODO in examples/readsdpa.c line 162,
446458 # -0.0 is used instead of 0.0 if the dual obj is <= 0., check if it has impact
447- DSDPSetY0 (dest. dsdp, constr, 0.0 )
459+ @check DSDPSetY0 (dest. dsdp, constr, 0.0 )
448460 end
449461 # TODO ComputeY0 as in examples/readsdpa.c
450462 empty! (dest. y)
@@ -462,7 +474,7 @@ function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike)
462474 ),
463475 )
464476 end
465- DSDPSetDualObjective (dest. dsdp, k, MOI. constant (set))
477+ @check DSDPSetDualObjective (dest. dsdp, k, MOI. constant (set))
466478 _new_A_matrix (dest)
467479 for t in func. terms
468480 if ! iszero (t. coefficient)
@@ -521,7 +533,7 @@ function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike)
521533 # Pass info to `dest.dsdp`
522534 if ! isempty (dest. lpdvars)
523535 lpcone = Ref {Ptr{Cvoid}} ()
524- DSDPCreateLPCone (dest. dsdp, lpcone)
536+ @check DSDPCreateLPCone (dest. dsdp, lpcone)
525537 dest. lpcone = lpcone[]
526538 nnzin, row, aval = _buildlp (
527539 length (dest. b) + 1 ,
@@ -531,7 +543,7 @@ function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike)
531543 )
532544 LPConeSetData (dest. lpcone, dest. nlpdrows, nnzin, row, aval)
533545 end
534- DSDPSetup (dest. dsdp)
546+ @check DSDPSetup (dest. dsdp)
535547 return index_map
536548end
537549
@@ -559,12 +571,13 @@ function _buildlp(nvars, lpdvars, lpdrows, lpcoefs)
559571end
560572
561573function MOI. optimize! (m:: Optimizer )
562- DSDPSolve (m. dsdp)
574+ @check DSDPSetStandardMonitor (m. dsdp, ! m. silent ? 1 : 0 )
575+ @check DSDPSolve (m. dsdp)
563576 # Calling `ComputeX` not right after `Solve` seems to sometime cause segfaults or weird Heisenbug's
564577 # let's call it directly what `DSDP/examples/readsdpa.c` does
565- DSDPComputeX (m. dsdp)
578+ @check DSDPComputeX (m. dsdp)
566579 m. y = zeros (Cdouble, length (m. b))
567- DSDPGetY (m. dsdp, m. y, length (m. y))
580+ @check DSDPGetY (m. dsdp, m. y, length (m. y))
568581 map! (- , m. y, m. y) # The primal objective is Max in SDOI but Min in DSDP
569582 return
570583end
@@ -574,7 +587,7 @@ function MOI.get(m::Optimizer, ::MOI.RawStatusString)
574587 return " `optimize!` not called"
575588 end
576589 stop = Ref {DSDPTerminationReason} ()
577- DSDPStopReason (m. dsdp, stop)
590+ @check DSDPStopReason (m. dsdp, stop)
578591 status = stop[]
579592 if status == DSDP_CONVERGED
580593 return " Converged"
@@ -603,11 +616,11 @@ function MOI.get(m::Optimizer, ::MOI.TerminationStatus)
603616 return MOI. OPTIMIZE_NOT_CALLED
604617 end
605618 stop = Ref {DSDPTerminationReason} ()
606- DSDPStopReason (m. dsdp, stop)
619+ @check DSDPStopReason (m. dsdp, stop)
607620 status = stop[]
608621 if status == DSDP_CONVERGED
609622 sol = Ref {DSDPSolutionType} ()
610- DSDPGetSolutionType (m. dsdp, sol)
623+ @check DSDPGetSolutionType (m. dsdp, sol)
611624 sol_status = sol[]
612625 if sol_status == DSDP_PDFEASIBLE
613626 return MOI. OPTIMAL
@@ -645,7 +658,7 @@ function MOI.get(m::Optimizer, attr::MOI.PrimalStatus)
645658 return MOI. NO_SOLUTION
646659 end
647660 sol = Ref {DSDPSolutionType} ()
648- DSDPGetSolutionType (m. dsdp, sol)
661+ @check DSDPGetSolutionType (m. dsdp, sol)
649662 status = sol[]
650663 if status == DSDP_PDUNKNOWN
651664 return MOI. UNKNOWN_RESULT_STATUS
@@ -664,7 +677,7 @@ function MOI.get(m::Optimizer, attr::MOI.DualStatus)
664677 return MOI. NO_SOLUTION
665678 end
666679 sol = Ref {DSDPSolutionType} ()
667- DSDPGetSolutionType (m. dsdp, sol)
680+ @check DSDPGetSolutionType (m. dsdp, sol)
668681 status = sol[]
669682 if status == DSDP_PDUNKNOWN
670683 return MOI. UNKNOWN_RESULT_STATUS
@@ -684,14 +697,14 @@ MOI.get(m::Optimizer, ::MOI.ResultCount) = m.dsdp == C_NULL ? 0 : 1
684697function MOI. get (m:: Optimizer , attr:: MOI.ObjectiveValue )
685698 MOI. check_result_index_bounds (m, attr)
686699 ret = Ref {Cdouble} ()
687- DSDPGetPPObjective (m. dsdp, ret)
700+ @check DSDPGetPPObjective (m. dsdp, ret)
688701 return m. objective_sign * ret[] + m. objective_constant
689702end
690703
691704function MOI. get (m:: Optimizer , attr:: MOI.DualObjectiveValue )
692705 MOI. check_result_index_bounds (m, attr)
693706 ret = Ref {Cdouble} ()
694- DSDPGetDDObjective (m. dsdp, ret)
707+ @check DSDPGetDDObjective (m. dsdp, ret)
695708 return m. objective_sign * ret[] + m. objective_constant
696709end
697710
@@ -826,7 +839,7 @@ function block(
826839end
827840
828841function vectorize_block (M, blk:: Integer , :: Type{MOI.Nonnegatives} )
829- return diag (block (M, blk))
842+ return LinearAlgebra . diag (block (M, blk))
830843end
831844
832845function vectorize_block (
0 commit comments