
/*
* This example shows how to formulate and solve the following MIP problem:
*
*        Maximize
*   Objective: x1 + 2 x2 + 3 x3 + x4
*   Subject to
*           c1: - x1 +   x2 + x3 +  10 x4 <= 20
*           c2:   x1 - 3 x2 + x3          <= 30
*           c3:          x2      - 3.5 x4  =  0
*   Bounds
*           0 <= x1 <= 40
*           2 <= x4 <= 3
*   General
*           x4 is integer
*
*           Expected results: x1=40; x2=10.5; x3=19.5; x4=3;
*/


#include <iostream>

#ifdef CGAL_USE_SCIP

#include <CGAL/SCIP_mixed_integer_program_traits.h>
typedef CGAL::SCIP_mixed_integer_program_traits<double>                        MIP_Solver;

#elif defined(CGAL_USE_GLPK)

#include <CGAL/GLPK_mixed_integer_program_traits.h>
typedef CGAL::GLPK_mixed_integer_program_traits<double>                        MIP_Solver;

#endif

typedef typename MIP_Solver::Variable                        Variable;
typedef typename MIP_Solver::Linear_objective        Linear_objective;
typedef typename MIP_Solver::Linear_constraint        Linear_constraint;


int main()
{
        MIP_Solver solver;

        // Variable x1
        Variable* x1 = solver.create_variable(Variable::CONTINUOUS, 0, 40, "x1");

        // Variable x2
        // You can create first (using default parameters) and then assign values.
        Variable* x2 = solver.create_variable();
        x2->set_name("x2");        // This is optional (a default will be given)

        // Variable x3
        Variable* x3 = solver.create_variable();        // Uses all default parameters
        x3->set_name("x3");

        // Variable x4
        Variable* x4 = solver.create_variable(Variable::INTEGER, 2, 3, "x4");

        // Objective.
        // Be careful this is "MAXIMIZE"
        Linear_objective * obj = solver.create_objective(Linear_objective::MAXIMIZE);
        obj->add_coefficient(x1, 1.0);
        obj->add_coefficient(x2, 2.0);
        obj->add_coefficient(x3, 3.0);
        obj->add_coefficient(x4, 1.0);

        // Constraint c1: -x1 + x2 + x3 + 10 x4 <= 20
        Linear_constraint* c1 = solver.create_constraint(-Linear_constraint::infinity(), 20, "c1");
        c1->add_coefficient(x1, -1);
        c1->add_coefficient(x2, 1);
        c1->add_coefficient(x3, 1);
        c1->add_coefficient(x4, 10);

        // Constraint c2: x1 - 3 x2 + x3 <= 30
        Linear_constraint* c2 = solver.create_constraint(-Linear_constraint::infinity(), 30, "c2");
        c2->add_coefficient(x1, 1);
        c2->add_coefficient(x2, -3);
        c2->add_coefficient(x3, 1);

        // Constraint c3:  x2 - 3.5 x4 = 0
        Linear_constraint* c3 = solver.create_constraint(0, 0, "c3");
        c3->add_coefficient(x2, 1);
        c3->add_coefficient(x4, -3.5);

        // Solve
        if (solver.solve()) {
                std::cout << "result: " << std::endl;
                const std::vector<double>& results = solver.solution();
                for (std::size_t i = 0; i < results.size(); ++i) {
                        std::cout << "\tx" << i + 1 << ": " << results[i] << std::endl;
                }
                return EXIT_SUCCESS;
        }
        else {
                std::cerr << "solving problem failed" << std::endl;
                return EXIT_FAILURE;
        }
}
