/* Copyright: Copyright (c) MOSEK ApS, Denmark. All rights reserved. File: solutionquality.cs Purpose: To demonstrate how to examine the quality of a solution. */ using System; namespace mosek.example { class msgclass : mosek.Stream { string prefix; public msgclass(string prfx) { prefix = prfx; } public override void streamCB(string msg) { Console.Write("{0}{1}", prefix, msg); } } public class solutionquality { public static void Main(String[] args) { if (args.Length == 0) { Console.WriteLine("Missing argument, syntax is:"); Console.WriteLine(" solutionquality inputfile"); } else { // Create a task object. using (mosek.Task task = new mosek.Task()) { task.set_Stream(mosek.streamtype.log, new msgclass("")); try { // We assume that a problem file was given as the first command // line argument (received in `args') task.readdata(args[0]); // Solve the problem task.optimize(); // Print a summary of the solution task.solutionsummary(mosek.streamtype.log); // Which solution to analyze mosek.soltype whichsol = mosek.soltype.bas; mosek.solsta solsta = task.getsolsta(whichsol); double pobj, pviolcon, pviolvar, pviolbarvar, pviolcones, pviolitg; double dobj, dviolcon, dviolvar, dviolbarvar, dviolcones; task.getsolutioninfo(whichsol, out pobj, out pviolcon, out pviolvar, out pviolbarvar, out pviolcones, out pviolitg, out dobj, out dviolcon, out dviolvar, out dviolbarvar, out dviolcones); switch (solsta) { case mosek.solsta.optimal: double abs_obj_gap = Math.Abs(dobj - pobj); double rel_obj_gap = abs_obj_gap / (1.0 + Math.Min(Math.Abs(pobj), Math.Abs(dobj))); double max_primal_viol = Math.Max(pviolcon, pviolvar); max_primal_viol = Math.Max(max_primal_viol, pviolbarvar); max_primal_viol = Math.Max(max_primal_viol, pviolcones); double max_dual_viol = Math.Max(dviolcon, dviolvar); max_dual_viol = Math.Max(max_dual_viol, dviolbarvar); max_dual_viol = Math.Max(max_dual_viol, dviolcones); // Assume the application needs the solution to be within // 1e-6 ofoptimality in an absolute sense. Another approach // would be looking at the relative objective gap Console.WriteLine("Customized solution information.\n"); Console.WriteLine(" Absolute objective gap: " + abs_obj_gap); Console.WriteLine(" Relative objective gap: " + rel_obj_gap); Console.WriteLine(" Max primal violation : " + max_primal_viol); Console.WriteLine(" Max dual violation : " + max_dual_viol); bool accepted = true; if (rel_obj_gap > 1e-6) { Console.WriteLine("Warning: The relative objective gap is LARGE."); accepted = false; } // We will accept a primal infeasibility of 1e-8 and // dual infeasibility of 1e-6. These number should chosen problem // dependent. if (max_primal_viol > 1e-8) { Console.WriteLine("Warning: Primal violation is too LARGE"); accepted = false; } if (max_dual_viol > 1e-6) { Console.WriteLine("Warning: Dual violation is too LARGE."); accepted = false; } if (accepted) { int numvar = task.getnumvar(); double[] xx = task.getxx(whichsol); Console.WriteLine("Optimal primal solution"); for (int j = 0; j < numvar; j++) Console.WriteLine("x[{0}]: {1}", j, xx[j]); } else { // print detailed information about the solution task.analyzesolution(mosek.streamtype.log, whichsol); } break; case mosek.solsta.dual_infeas_cer: case mosek.solsta.prim_infeas_cer: Console.WriteLine("Primal or dual infeasibility certificate found."); break; case mosek.solsta.unknown: Console.WriteLine("The status of the solution is unknown."); break; default: Console.WriteLine("Other solution status"); break; } } catch (mosek.Exception e) { Console.WriteLine("\nAn error occourred: " + e.Code); Console.WriteLine(e); //throw; } } } } } }