Possible Issues and Troubleshooting

We now demonstrate some current limitations of this package via Convex.jl#master's Problem Depot. This is run with TEST=true, meaning the solution returned by the solver will be tested against the true solution.

Underflows

This occurs when the precision used to represent the solution is not high enough compared to the internal precision used by the solver. This lack of precision can lead to catastrophic cancellation. In the following, SDPA-QD is used to solve the problem, and Float64 numbers are used to represent the obtained solution, and the test fails.

julia> test_problem = Convex.ProblemDepot.PROBLEMS["affine"]["affine_Diagonal_atom"];
julia> TEST = true; atol = 1e-3; rtol = 0.0;
julia> test_problem(Val(TEST), atol, rtol, Float64) do problem solve!(problem, SDPAFamily.Optimizer{Float64}(variant=:sdpa_qd, silent=true)) end┌ Warning: Problem status INFEASIBLE; solution may be inaccurate. └ @ Convex ~/.julia/packages/Convex/tSTAW/src/solution.jl:342 Test Passed

We try to automatically detect underflows and warn against them; in this case, the warning is issued. Sometimes this can be avoided by choosing a better set of parameters. See Choice of parameters.

Presolve

The usefulness of our presolve routine is demonstrated in Using presolve. However, our presolve subroutine simply uses naïve Gaussian elimination and has its limitations. At its core, the reduce! method takes in a sparse matrix where each row is a linearized constraint matrix and apply Gaussian elimination with pivoting to identify the linear independence. This process is not numerically stable, and we cannot guarantee that all linear dependent entries will be identified.

This is demonstrated in the following example. We explicitly construct a matrix with linearly dependent rows. However, due to its numerical instability, we can only identify a subset of them.

julia> M = sprand(100, 20000, 0.03);
julia> λ = rand();
julia> M[1, :] = λ*M[3, :] + (1-λ)*M[7, :];
julia> rows = Set(rowvals(SDPAFamily.reduce!(M)[:, 1:end-1]));
julia> redundant = collect(setdiff!(Set(1:10), rows));
julia> @test length(redundant) >= 1Test Passed

Choice of parameters

Unfortunately, we have not been able to successfully solve every problem that we have tried with one choice of parameters. We have chosen default parameter settings that we hope will work with a wide variety of problems. See Usage for details on switching to two other sets of parameters provided by the solvers.

This is an example where a better choice of parameters can help.

julia> test_problem = Convex.ProblemDepot.PROBLEMS["lp"]["lp_dotsort_atom"];
julia> TEST = true; atol = 1e-3; rtol = 0.0;
julia> test_problem(Val(TEST), atol, rtol, Float64) do problem solve!(problem, SDPAFamily.Optimizer{Float64}(variant=:sdpa_dd, silent=true)) end┌ Warning: Problem status ITERATION_LIMIT; solution may be inaccurate. └ @ Convex ~/.julia/packages/Convex/tSTAW/src/solution.jl:342 Test Failed at /home/runner/.julia/packages/Convex/tSTAW/src/problem_depot/problems/lp.jl:307 Expression: ≈(p.optval, 19, atol = atol, rtol = rtol) Evaluated: -9009.485296833393 ≈ 19 (atol=0.001, rtol=0.0) ERROR: There was an error during testing
julia> test_problem = Convex.ProblemDepot.PROBLEMS["lp"]["lp_dotsort_atom"];
julia> TEST = true; atol = 1e-3; rtol = 0.0;
julia> test_problem(Val(TEST), atol, rtol, Float64) do problem solve!(problem, SDPAFamily.Optimizer{Float64}(variant=:sdpa_dd, silent=true, params = SDPAFamily.UNSTABLE_BUT_FAST)) end┌ Warning: Problem status ITERATION_LIMIT; solution may be inaccurate. └ @ Convex ~/.julia/packages/Convex/tSTAW/src/solution.jl:342 Test Failed at /home/runner/.julia/packages/Convex/tSTAW/src/problem_depot/problems/lp.jl:307 Expression: ≈(p.optval, 19, atol = atol, rtol = rtol) Evaluated: 9.631100304229781 ≈ 19 (atol=0.001, rtol=0.0) ERROR: There was an error during testing

Summary of problematic problems

Due to the above reasons, we have modified the default settings for the following tests from Convex.jl's `Problem Depot'.

SolverUnderflowNeed to use params = SDPAFamily.UNSTABLE_BUT_FASTPresolve disabled due to long runtime
:sdpa_ddaffine_Partial_transposeaffine_Partial_transpose lp_pos_atom lp_neg_atom sdp_matrix_frac_atom lp_dotsort_atomaffine_Partial_transpose lp_min_atom lp_max_atom
:sdpa_qdaffine_Partial_transpose affine_Diagonal_atomaffine_Partial_transpose affine_Diagonal_atomaffine_Partial_transpose lp_min_atom lp_max_atom
:sdpa_gmpaffine_Partial_transposeaffine_Partial_transposeaffine_Partial_transpose lp_min_atom lp_max_atom

In addition, we have excluded lp_dotsort_atom and lp_pos_atom when testing :sdpa due to imprecise solutions using default parameters. We have also excluded all second-order cone problems when using BigFloat or Double64 numeric types, due to MathOptInterface.jl#876, as well as the sdp_lambda_max_atom problem due to GenericLinearAlgebra#47. Both these issues have been fixed on the master branches of the respective packages, so these exclusions will be removed once new versions are released.

Troubleshooting

When the solvers fail to return a solution, we recommend trying out the following troubleshoot steps.

  1. Set silent=false and look for warnings and error messages. If necessary, check the output file. Its path is printed by the solver output and can also be retrieved via Optimizer.tempdir.
  2. Set presolve=true to remove redundant constraints. Typically, redundant constraints are indicated by a premature cholesky miss error as shown above.
  3. Use BigFloat (the default) or Double64 (from the DoubleFloats package) precision instead of Float64 (e.g. SDPAFamily.Optimizer{Double64}(...)). This will reduce the chance of having underflow errors when reading back the results.
  4. Change the parameters by passing choices of parameters, e.g. SDPAFamily.Optimizer(params=(SDPAFamily.UNSTABLE_BUT_FAST)), or SDPAFamily.Optimizer(params=(epsilonDash=1e-40,)). It might be helpful to use a tighter choice of the epsilonDash and epsilonStar parameters. See Usage and Changing parameters & solving at very high precision for more options and examples.