ERGO-Code / HiGHS

Linear optimization software
MIT License
992 stars 184 forks source link

Solver not detecting variables as integer #1109

Closed SanPen closed 1 year ago

SanPen commented 1 year ago

Hello,

I am using Highs from C++ using a modelling language I made.

The current process where I'm struggling is the following:

The problem I'm having is that the results for the integer variables are not integer (and not remotely close to being integer) say, a binary variable result is 0.048. See test B below.

Other tests:

The results from the CMD with IPM (test B) are the same results obtained via the C++ interface. When I run the C++ code with the simplex option I don't seem to get the correct results either.

I'm using Highs 1.2.2. and 1.4.1. Both have the same behavior.

Thanks

odow commented 1 year ago

Forcing the interior point code ignores integrality. Don't use the --solver ipm option.

SanPen commented 1 year ago

How can I do that from the C++ interface?

Also, the simplex method is not the best for the power systems simulations I'm doing.

Not setting _highs.setOptionValue("solver", kSimplexString); or _highs.setOptionValue("solver", kIpmString); makes it work.

Will it do the switching from simplex to IP automatically? how does it work?

odow commented 1 year ago

You want to change the solution method of the root node? This is currently not possible.

See

SanPen commented 1 year ago

So, for future viewers: Do not set the solver option when solving a MIP

mingodad commented 1 year ago

Hello @SanPen is you modelling language visible somewhere ? I did a fork of GLPK here https://github.com/mingodad/GLPK and I'm interested in know your to compare.

SanPen commented 1 year ago

Hi Domingo,

I believe what I've done is different from MathProg. As I understand it, MathProg is a language that serves to create files that are later interpreted by the solver (like GAMS or AMPL).

What I've done is simmilar to ORTools, PuLP, CVXPY and the likes; A set of C++ objects that allow you to declare optimization programs as you would write matlab code.

Example:

    /**
     * Model from chapter 8
     * Book: Mathematical Programming for Power Systems Operation - Alejandro Garcés Ruíz
     * pag 148-149
     */

    // generator quadratic costs (a * P^2 + b * P + c)
    vec a = {0.0004984, 0.001246, 0.00623};
    vec b = {16.821, 40.6196, 21.9296};
    vec c = {220.4174, 161.8554, 171.2004};

    // startup costs
    vec c_up = {124.69, 249.22, 0};

    // initial startup state
    vec z_ini = {1, 1, 0};

    // power bounds
    vec pmax = {220, 100, 20};
    vec pmin = {100, 10, 10};

    // demand
    vec d = {178.690, 168.450, 161.840, 157.830, 158.160, 163.690,
             176.860, 194.210, 209.670, 221.540, 233.180, 240.820,
             247.030, 248.470, 253.830, 260.900, 261.120, 251.680,
             250.890, 242.100, 242.050, 231.680, 205.070, 200.690};

    LpProblem prob("MIP 3 generators");

    uword T = d.size();
    uword n_gen = a.size();

    LpMat zeta = prob.addVarsMat("zeta", n_gen, T, 0, 1, LpVarType::Integer);
    LpMat mu = prob.addVarsMat("mu", n_gen, T, 0, 1, LpVarType::Integer);
    LpMat delta = prob.addVarsMat("delta", n_gen, T, 0, 1, LpVarType::Integer);
    LpMat p = prob.addVarsMat("p", n_gen, T, -LpInfinity, LpInfinity, LpVarType::Continuous);

    LpSequencePtr fop = std::make_shared<LpSequence>();
    LpSequencePtr fsup = std::make_shared<LpSequence>();

    for (uword t=0; t < T; ++t){  // for each time step

        // production equals demand
        prob << (p.sumCol(t) == d[t]);

        for(uword k=0; k < n_gen; ++k) {  // for each generator

            // Operational cost (linear...)
            fop += (b[k] * p(k, t) + c[k] * zeta(k, t) );

            // start-up cost
            fsup += (c_up[k] * mu(k, t));

            // power boundaries of the generator
            prob << (p(k, t) >= (pmin[k] * zeta(k, t)));
            prob << (p(k, t) <= (pmax[k] * zeta(k, t)));

            // binary algebra to set the relationship between start-up, shutting-down and operation binary vars
            if (t == 0) {
                prob << (mu(k, 0) - delta(k, 0) == zeta(k, 0) - z_ini[k]);
                prob << (mu(k, 0) + delta(k, 0) <= 1);
            } else {
                prob << (mu(k, t) - delta(k, t) == zeta(k, t) - zeta(k, t-1));
                prob << (mu(k, t) + delta(k, t) <= 1);
            };
        }
    }

    prob.min(fop + fsup);

    LpHighsInterface solver(false, 0, false, false);

    LpResult res = solver.solve(prob);

    mat zeta_val = res.getVarSolutionFromMat(zeta);
    mat mu_val = res.getVarSolutionFromMat(mu);
    mat delta_val = res.getVarSolutionFromMat(delta);
    mat p_val = res.getVarSolutionFromMat(p);

I don't plan to open source it, at least not yet.

mingodad commented 1 year ago

Thank you for reply !