//
//    Copyright: Copyright (c) MOSEK ApS, Denmark. All rights reserved.
//
//    File:    midual1.java
//
//    Purpose:  Demonstrates how to compute dual values with
//              respect to a fixed integer solution for a MIO problem.
//
//              minimize    500 s1 + 300 s2 + 10 x1 + 14 x2
//              subject to  x1 + x2 >= 100
//                          0 <= x1 <= 70 s1
//                          0 <= x2 <= 80 s2
//                          s1, s2 - binary
//
package com.mosek.example.fusion;
import com.mosek.mosek.fusion.*;

public class midual1 {
  public static void main(String[] args)
  throws SolutionError, java.lang.Exception {

    /* M is the initial mixed-integer model */
    try(Model M = new Model("midual1"))
    {
      Variable x = M.variable("x", 2, Domain.greaterThan(0));
      Variable s = M.variable("s", 2, Domain.binary());

      M.objective(ObjectiveSense.Minimize,
                  Expr.add(Expr.dot(new double[]{10,14}, x), Expr.dot(new double[]{500,300}, s)));

      M.constraint("demand",
                   Expr.sum(x), Domain.greaterThan(100));
      M.constraint("production",
                   Expr.sub(x, Expr.mulElm(new double[]{70,80}, s)), Domain.lessThan(0));

      M.solve();

      if (M.getProblemStatus() != ProblemStatus.PrimalFeasible)
        throw new java.lang.Exception("Unsuitable problem status, exiting");

      System.out.printf("x = %f, %f\n", x.level()[0], x.level()[1]);

      /* F is the continuous fixed model */
      try(Model F = M.getFixedModel())
      {
        F.solve();

        if (F.getProblemStatus() != ProblemStatus.PrimalAndDualFeasible)
          throw new java.lang.Exception("Unsuitable problem status, exiting");

        Constraint demand = F.getConstraint("demand");
        Constraint production = F.getConstraint("production");
        Variable xfix = F.getVariable("x");

        System.out.printf("xfix = %f, %f\n", xfix.level()[0], xfix.level()[1]);
        System.out.printf("demand dual = %f\n", demand.dual()[0]);
        System.out.printf("production dual = %f, %f\n", production.dual()[0], production.dual()[1]);
      }
    }
  }
}
