c++linear-programmingcoin-or-cbc

Linear Programming: Modulo constraint


I am using Coin-Or's rehearse to implement linear programming.

I need a modulo constraint. Example: x shall be a multiple of 3.

OsiCbcSolverInterface solver;
CelModel model(solver);
CelNumVar x;
CelIntVar z;

unsigned int mod = 3;

// Maximize

solver.setObjSense(-1.0);

model.setObjective(x);

model.addConstraint(x <= 7.5);

// The modulo constraint:

model.addConstraint(x == z * mod);

The result for x should be 6. However, z is set to 2.5, which should not be possible as I declared it as a CellIntVar.

How can I enforce z to be an integer?


Solution

  • I never used that lib, but you i think you should follow the tests.

    The core message comes from the readme:

    If you want some of your variables to be integers, use CelIntVar instead of CelNumVar. You must bind the solver to an Integer Linear Programming solver as well, for example Coin-cbc.

    Looking at Rehearse/tests/testRehearse.cpp -> exemple4() (here presented: incomplete code; no copy-paste):

    OsiClpSolverInterface *solver = new OsiClpSolverInterface();
    
    CelModel model(*solver);
    
    ...
    CelIntVar x1("x1");
    ...
    solver->initialSolve();       // this is the relaxation (and maybe presolving)!
    ...
    CbcModel cbcModel(*solver);   // MIP-solver
    cbcModel.branchAndBound();    // Use MIP-solver
    
    printf("Solution for x1 : %g\n", model.getSolutionValue(x1, *cbcModel.solver()));
    printf("Solution objvalue = : %g\n", cbcModel.solver()->getObjValue());
    

    This kind of usage (use Osi to get LP-solver; build MIP-solver on top of that Osi-provided-LP-solver and call brandAndBound) basically follows Cbc's internal interface (with python's cylp this looks similar).

    Just as reference: This is the official CoinOR Cbc (Rehearse-free) example from here:

    // Copyright (C) 2005, International Business Machines
    // Corporation and others.  All Rights Reserved.
    
    #include "CbcModel.hpp"
    
    // Using CLP as the solver
    #include "OsiClpSolverInterface.hpp"
    
    int main (int argc, const char *argv[])
    {
      OsiClpSolverInterface solver1;
    
      // Read in example model in MPS file format
      // and assert that it is a clean model
      int numMpsReadErrors = solver1.readMps("../../Mps/Sample/p0033.mps","");
      assert(numMpsReadErrors==0);
    
      // Pass the solver with the problem to be solved to CbcModel 
      CbcModel model(solver1);
    
      // Do complete search
      model.branchAndBound();
    
      /* Print the solution.  CbcModel clones the solver so we
         need to get current copy from the CbcModel */
      int numberColumns = model.solver()->getNumCols();
    
      const double * solution = model.bestSolution();
    
      for (int iColumn=0;iColumn<numberColumns;iColumn++) {
        double value=solution[iColumn];
        if (fabs(value)>1.0e-7&&model.solver()->isInteger(iColumn)) 
          printf("%d has value %g\n",iColumn,value);
       }
      return 0;
    }