/*
  Copyright: Copyright (c) MOSEK ApS, Denmark. All rights reserved.

  File:      sensitivity.cs

  Purpose:   To demonstrate how to perform sensitivity
  analysis from the API on a small problem:

  minimize

  obj: +1 x11 + 2 x12 + 5 x23 + 2 x24 + 1 x31 + 2 x33 + 1 x34
  st
  c1:   +  x11 +   x12                                           <= 400
  c2:                  +   x23 +   x24                           <= 1200
  c3:                                  +   x31 +   x33 +   x34   <= 1000
  c4:   +  x11                         +   x31                   = 800
  c5:          +   x12                                           = 100
  c6:                  +   x23                 +   x33           = 500
  c7:                          +   x24                 +   x34   = 500

  The example uses basis type sensitivity analysis.
*/
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 sensitivity
  {
    public static void Main ()
    {
      const double
      infinity = 0;

      mosek.boundkey[] bkc = new mosek.boundkey[] {
        mosek.boundkey.up, mosek.boundkey.up,
        mosek.boundkey.up, mosek.boundkey.fx,
        mosek.boundkey.fx, mosek.boundkey.fx,
        mosek.boundkey.fx
      };

      mosek.boundkey[] bkx = new mosek.boundkey[] {
        mosek.boundkey.lo, mosek.boundkey.lo,
        mosek.boundkey.lo, mosek.boundkey.lo,
        mosek.boundkey.lo, mosek.boundkey.lo,
        mosek.boundkey.lo
      };

      int[] ptrb = new int[] {0, 2, 4, 6, 8, 10, 12};
      int[] ptre = new int[] {2, 4, 6, 8, 10, 12, 14};
      int[] sub = new int[] {0, 3, 0, 4, 1, 5, 1, 6, 2, 3, 2, 5, 2, 6};
      double[] blc = new double[] {
        -infinity, -infinity,
        -infinity, 800, 100, 500, 500
      };

      double[] buc = new double[] {400, 1200, 1000, 800, 100, 500, 500};
      double[] c   = new double[] {1.0, 2.0, 5.0, 2.0, 1.0, 2.0, 1.0};
      double[] blx = new double[] {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
      double[] bux = new double[] {infinity,
                                   infinity,
                                   infinity,
                                   infinity,
                                   infinity,
                                   infinity,
                                   infinity
                                  };

      double[] val = new double[] {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
                                   1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
                                  };

      int numcon = 7;  /* Number of constraints.             */
      int numvar = 7;  /* Number of variables.               */
      try
      {
        using (mosek.Task task = new mosek.Task())
        {
          // Directs the log task stream to the user specified
          // method task_msg_obj.streamCB
          task.set_Stream(mosek.streamtype.log, new msgclass (""));

          task.inputdata(numcon, numvar,
                         c,
                         0.0,
                         ptrb,
                         ptre,
                         sub,
                         val,
                         bkc,
                         blc,
                         buc,
                         bkx,
                         blx,
                         bux);

          /* A maximization problem */
          task.putobjsense(mosek.objsense.minimize);

          try
          {
            task.optimize();
          }
          catch (mosek.Warning w)
          {
            Console.WriteLine("Mosek warning:");
            Console.WriteLine (w.Code);
            Console.WriteLine (w);
          }


          /* Analyze upper bound on c1 and the equality constraint on c4 */
          int[] subi  = new int [] {0, 3};
          mosek.mark[] marki = new mosek.mark[] {mosek.mark.up,
                                                 mosek.mark.up
                                                };

          /* Analyze lower bound on the variables x12 and x31 */
          int[] subj  = new int [] {1, 4};
          mosek.mark[] markj = new mosek.mark[] {mosek.mark.lo,
                                                 mosek.mark.lo
                                                };

          double[] leftpricei  = new  double[2];
          double[] rightpricei = new  double[2];
          double[] leftrangei  = new  double[2];
          double[] rightrangei = new  double[2];
          double[] leftpricej  = new  double[2];
          double[] rightpricej = new  double[2];
          double[] leftrangej  = new  double[2];
          double[] rightrangej = new  double[2];


          task.primalsensitivity( subi,
                                  marki,
                                  subj,
                                  markj,
                                  leftpricei,
                                  rightpricei,
                                  leftrangei,
                                  rightrangei,
                                  leftpricej,
                                  rightpricej,
                                  leftrangej,
                                  rightrangej);

          Console.Write("Results from sensitivity analysis on bounds:\n");

          Console.Write("For constraints:\n");
          for (int i = 0; i < 2; ++i)
            Console.Write(
              "leftprice = {0}, rightprice = {1}, leftrange = {2}, rightrange = {3}\n",
              leftpricei[i], rightpricei[i], leftrangei[i], rightrangei[i]);

          Console.Write("For variables:\n");
          for (int i = 0; i < 2; ++i)
            Console.Write(
              "leftprice = {0}, rightprice = {1}, leftrange = {2}, rightrange = {3}\n",
              leftpricej[i], rightpricej[i], leftrangej[i], rightrangej[i]);


          double[] leftprice  = new  double[2];
          double[] rightprice = new  double[2];
          double[] leftrange  = new  double[2];
          double[] rightrange = new  double[2];
          int[] subc = new int[] {2, 5};

          task.dualsensitivity(  subc,
                                 leftprice,
                                 rightprice,
                                 leftrange,
                                 rightrange
                              );

          Console.Write("Results from sensitivity analysis on objective coefficients:");

          for (int i = 0; i < 2; ++i)
            Console.Write(
              "leftprice = {0}, rightprice = {1}, leftrange = {2}, rightrange = {3}\n",
              leftprice[i], rightprice[i], leftrange[i], rightrange[i]);
        }
      }
      catch (mosek.Exception e)
      {
        Console.WriteLine (e.Code);
        Console.WriteLine (e);
        throw;
      }
    }
  }
}
