##
#    Copyright: Copyright (c) MOSEK ApS, Denmark. All rights reserved.
#
#    File:    midual1.py
#
#    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
##
import mosek, sys

midual1_ptf = """Task midual1
Objective
    Minimize + 10 x1 + 14 x2 + 500 s1 + 300 s2
Constraints
    'demand' [100] + x1 + x2
    'production1' [-inf;0] + x1 - 70 s1
    'production2' [-inf;0] + x2 - 80 s2
Variables
    x1 [0;+inf]
    x2 [0;+inf]
    s1 [0;1]
    s2 [0;1]
Integers
    s1 s2
"""

with mosek.Task() as task:
    task.set_Stream(mosek.streamtype.log, sys.stdout.write)
    task.putintparam(mosek.iparam.log_include_summary, 1)

    # Construct the initial mixed-integer task
    task.readptfstring(midual1_ptf)

    task.optimize()

    if task.getprosta(mosek.soltype.itg) != mosek.prosta.prim_feas:
        raise Exception("Unsuitable problem status, exiting")

    xx = task.getxxslice(mosek.soltype.itg, 0, 2)
    print(f"x = {xx[0]}, {xx[1]}")

    # Constructing the continuous task with fixed variables
    with task.getfixedproblem() as fixTask:
        fixTask.set_Stream(mosek.streamtype.log, sys.stdout.write)

        fixTask.optimize()

        if fixTask.getprosta(mosek.soltype.bas) != mosek.prosta.prim_and_dual_feas:
            raise Exception("Unsuitable problem status, exiting")

        xfix = fixTask.getxxslice(mosek.soltype.bas, 0, 2)
        y = fixTask.getyslice(mosek.soltype.bas, 0, 3)

        print(f"xfix = {xfix[0]}, {xfix[1]}")
        print(f"demand dual = {y[0]}")
        print(f"production dual = {y[1]}, {y[2]}")
