7.2 Errors and exceptions

Exceptions

Almost every function in Optimizer API for .NET can throw an exception informing that the requested operation was not performed correctly, and indicating the type of error that occurred. This is the case in situations such as for instance:

  • referencing a nonexisting variable (for example with too large index),
  • defining an invalid value for a parameter,
  • accessing an undefined solution,
  • repeating a variable name, etc.

It is therefore a good idea to catch exceptions of type Error. The one case where it is extremely important to do so is when Task.optimize is invoked. We will say more about this in Sec. 7.1 (Accessing the solution).

The exception contains a response code (element of the enum rescode) and short diagnostic messages. They can be accessed as in the following example.

  try {
    task.putdouparam(mosek.dparam.intpnt_co_tol_rel_gap, -1.0e-7);
  }
  catch (mosek.Exception e) {
    mosek.rescode res = e.Code;
    Console.WriteLine("Response code {0}\nMessage       {1}", res, e.Message);
  }

It will produce as output:

Response code rescode.err_param_is_too_small
Message       The parameter value -1e-07 is too small for parameter 'MSK_DPAR_INTPNT_CO_TOL_REL_GAP'.

Another way to obtain a human-readable string corresponding to a response code is the method Env.getcodedesc. A full list of exceptions, as well as response codes, can be found in the API reference.

Optimizer errors and warnings

The optimizer may also produce warning messages. They indicate non-critical but important events, that will not prevent solver execution, but may be an indication that something in the optimization problem might be improved. Warning messages are normally printed to a log stream (see Sec. 7.3 (Input/Output)). A typical warning is, for example:

MOSEK warning 53: A numerically large upper bound value  6.6e+09 is specified for constraint 'C69200' (46020).

Warnings can also be suppressed by setting the iparam.max_num_warnings parameter to zero, if they are well-understood.

Error and solution status handling example

Below is a source code example with a simple framework for handling major errors when assessing and retrieving the solution to a conic optimization problem.

Listing 7.2 Sample framework for checking optimization result. Click here to download.
using System;
using mosek;
using System.Text;

namespace mosek.example
{
  // A log handler class
  class msgclass : mosek.Stream
  {
    public msgclass () {}
    public override void streamCB (string msg) { Console.Write ("{0}", msg); }
  }

  public class response
  {
    public static void Main(string[] argv)
    {
      StringBuilder symname = new StringBuilder();
      StringBuilder desc = new StringBuilder();

      string filename;
      if (argv.Length >= 1) filename = argv[0];
      else                  filename = "../data/cqo1.mps";

      // Define environment and task
      using (Env env = new Env())
      {
        using (Task task = new Task(env, 0, 0))
        {
          try 
          {
            // (Optionally) set a log handler
            // task.set_Stream (streamtype.log, new msgclass ());

            // (Optionally) uncomment this to get solution status unknown
            // task.putintparam(iparam.intpnt_max_iterations, 1);

            // In this example we read data from a file
            task.readdata(filename);

            // Perform optimization
            rescode trm = task.optimize();
            task.solutionsummary(streamtype.log);

            // Handle solution status. We expect Optimal
            solsta solsta = task.getsolsta(soltype.itr);

            switch ( solsta )
            {
              case solsta.optimal:
                // Optimal solution. Print variable values
                Console.WriteLine("An optimal interior-point solution is located.");
                int numvar = task.getnumvar();
                double[] xx = new double[numvar];
                task.getxx(soltype.itr, xx);
                for(int i = 0; i < numvar; i++) 
                  Console.WriteLine("x[" + i + "] = " + xx[i]);
                break;

              case solsta.dual_infeas_cer:
                Console.WriteLine("Dual infeasibility certificate found.");
                break;

              case solsta.prim_infeas_cer:
                Console.WriteLine("Primal infeasibility certificate found.");
                break;

              case solsta.unknown:
                /* The solutions status is unknown. The termination code
                   indicates why the optimizer terminated prematurely. */
                Console.WriteLine("The solution status is unknown.");
                Env.getcodedesc(trm, symname, desc);
                Console.WriteLine("  Termination code: {0} {1}", symname, desc);
                break;

              default:
                Console.WriteLine("An unexpected solution status " + solsta);
                break;
            }
          }
          catch (mosek.Error e)
          {
            Console.WriteLine("Unexpected optimization error ({0}) {1}", e.Code, e.Message);
          }
        }
      }
    }
  }
}