Exemple #1
0
 virtual int chooseVariable( OsiSolverInterface * solver,
                             OsiBranchingInformation * info,
                             bool fixVariables){
   if(numberUnsatisfied_){
     int chosen = (int) (floor(CoinDrand48() * (numberUnsatisfied_)));
     bestObjectIndex_ = list_[chosen];
     bestWhichWay_ = solver->object(bestObjectIndex_)->whichWay();
     firstForcedObjectIndex_ = -1;
     firstForcedWhichWay_ =-1;
     return 0;
   }
   else {
     return 1;
   }
 }
Exemple #2
0
int main (int argc, const char *argv[])
{
     ClpSimplex  model;
     int status;
     // Keep names
     if (argc < 2) {
          status = model.readMps("small.mps", true);
     } else {
          status = model.readMps(argv[1], false);
     }
     if (status)
          exit(10);
     /*
       This driver implements a method of treating a problem as all cuts.
       So it adds in all E rows, solves and then adds in violated rows.
     */

     double time1 = CoinCpuTime();
     ClpSimplex * model2;
     ClpPresolve pinfo;
     int numberPasses = 5; // can change this
     /* Use a tolerance of 1.0e-8 for feasibility, treat problem as
        not being integer, do "numberpasses" passes and throw away names
        in presolved model */
     model2 = pinfo.presolvedModel(model, 1.0e-8, false, numberPasses, false);
     if (!model2) {
          fprintf(stderr, "ClpPresolve says %s is infeasible with tolerance of %g\n",
                  argv[1], 1.0e-8);
          fprintf(stdout, "ClpPresolve says %s is infeasible with tolerance of %g\n",
                  argv[1], 1.0e-8);
          // model was infeasible - maybe try again with looser tolerances
          model2 = pinfo.presolvedModel(model, 1.0e-7, false, numberPasses, false);
          if (!model2) {
               fprintf(stderr, "ClpPresolve says %s is infeasible with tolerance of %g\n",
                       argv[1], 1.0e-7);
               fprintf(stdout, "ClpPresolve says %s is infeasible with tolerance of %g\n",
                       argv[1], 1.0e-7);
               exit(2);
          }
     }
     // change factorization frequency from 200
     model2->setFactorizationFrequency(100 + model2->numberRows() / 50);

     int numberColumns = model2->numberColumns();
     int originalNumberRows = model2->numberRows();

     // We will need arrays to choose rows to add
     double * weight = new double [originalNumberRows];
     int * sort = new int [originalNumberRows];
     int numberSort = 0;
     char * take = new char [originalNumberRows];

     const double * rowLower = model2->rowLower();
     const double * rowUpper = model2->rowUpper();
     int iRow, iColumn;
     // Set up initial list
     numberSort = 0;
     for (iRow = 0; iRow < originalNumberRows; iRow++) {
          weight[iRow] = 1.123e50;
          if (rowLower[iRow] == rowUpper[iRow]) {
               sort[numberSort++] = iRow;
               weight[iRow] = 0.0;
          }
     }
     numberSort /= 2;
     // Just add this number of rows each time in small problem
     int smallNumberRows = 2 * numberColumns;
     smallNumberRows = CoinMin(smallNumberRows, originalNumberRows / 20);
     // and pad out with random rows
     double ratio = ((double)(smallNumberRows - numberSort)) / ((double) originalNumberRows);
     for (iRow = 0; iRow < originalNumberRows; iRow++) {
          if (weight[iRow] == 1.123e50 && CoinDrand48() < ratio)
               sort[numberSort++] = iRow;
     }
     /* This is optional.
        The best thing to do is to miss out random rows and do a set which makes dual feasible.
        If that is not possible then make sure variables have bounds.

        One way that normally works is to automatically tighten bounds.
     */
#if 0
     // However for some we need to do anyway
     double * columnLower = model2->columnLower();
     double * columnUpper = model2->columnUpper();
     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          columnLower[iColumn] = CoinMax(-1.0e6, columnLower[iColumn]);
          columnUpper[iColumn] = CoinMin(1.0e6, columnUpper[iColumn]);
     }
#endif
     model2->tightenPrimalBounds(-1.0e4, true);
     printf("%d rows in initial problem\n", numberSort);
     double * fullSolution = model2->primalRowSolution();

     // Just do this number of passes
     int maxPass = 50;
     // And take out slack rows until this pass
     int takeOutPass = 30;
     int iPass;

     const int * start = model2->clpMatrix()->getVectorStarts();
     const int * length = model2->clpMatrix()->getVectorLengths();
     const int * row = model2->clpMatrix()->getIndices();
     int * whichColumns = new int [numberColumns];
     for (iColumn = 0; iColumn < numberColumns; iColumn++)
          whichColumns[iColumn] = iColumn;
     int numberSmallColumns = numberColumns;
     for (iPass = 0; iPass < maxPass; iPass++) {
          printf("Start of pass %d\n", iPass);
          // Cleaner this way
          std::sort(sort, sort + numberSort);
          // Create small problem
          ClpSimplex small(model2, numberSort, sort, numberSmallColumns, whichColumns);
          small.setFactorizationFrequency(100 + numberSort / 200);
          //small.setPerturbation(50);
          //small.setLogLevel(63);
          // A variation is to just do N iterations
          //if (iPass)
          //small.setMaximumIterations(100);
          // Solve
          small.factorization()->messageLevel(8);
          if (iPass) {
               small.dual();
          } else {
               small.writeMps("continf.mps");
               ClpSolve solveOptions;
               solveOptions.setSolveType(ClpSolve::useDual);
               //solveOptions.setSolveType(ClpSolve::usePrimalorSprint);
               //solveOptions.setSpecialOption(1,2,200); // idiot
               small.initialSolve(solveOptions);
          }
          bool dualInfeasible = (small.status() == 2);
          // move solution back
          double * solution = model2->primalColumnSolution();
          const double * smallSolution = small.primalColumnSolution();
          for (int j = 0; j < numberSmallColumns; j++) {
               iColumn = whichColumns[j];
               solution[iColumn] = smallSolution[j];
               model2->setColumnStatus(iColumn, small.getColumnStatus(j));
          }
          for (iRow = 0; iRow < numberSort; iRow++) {
               int kRow = sort[iRow];
               model2->setRowStatus(kRow, small.getRowStatus(iRow));
          }
          // compute full solution
          memset(fullSolution, 0, originalNumberRows * sizeof(double));
          model2->times(1.0, model2->primalColumnSolution(), fullSolution);
          if (iPass != maxPass - 1) {
               // Mark row as not looked at
               for (iRow = 0; iRow < originalNumberRows; iRow++)
                    weight[iRow] = 1.123e50;
               // Look at rows already in small problem
               int iSort;
               int numberDropped = 0;
               int numberKept = 0;
               int numberBinding = 0;
               int numberInfeasibilities = 0;
               double sumInfeasibilities = 0.0;
               for (iSort = 0; iSort < numberSort; iSort++) {
                    iRow = sort[iSort];
                    //printf("%d %g %g\n",iRow,fullSolution[iRow],small.primalRowSolution()[iSort]);
                    if (model2->getRowStatus(iRow) == ClpSimplex::basic) {
                         // Basic - we can get rid of if early on
                         if (iPass < takeOutPass && !dualInfeasible) {
                              // may have hit max iterations so check
                              double infeasibility = CoinMax(fullSolution[iRow] - rowUpper[iRow],
                                                             rowLower[iRow] - fullSolution[iRow]);
                              weight[iRow] = -infeasibility;
                              if (infeasibility > 1.0e-8) {
                                   numberInfeasibilities++;
                                   sumInfeasibilities += infeasibility;
                              } else {
                                   weight[iRow] = 1.0;
                                   numberDropped++;
                              }
                         } else {
                              // keep
                              weight[iRow] = -1.0e40;
                              numberKept++;
                         }
                    } else {
                         // keep
                         weight[iRow] = -1.0e50;
                         numberKept++;
                         numberBinding++;
                    }
               }
               // Now rest
               for (iRow = 0; iRow < originalNumberRows; iRow++) {
                    sort[iRow] = iRow;
                    if (weight[iRow] == 1.123e50) {
                         // not looked at yet
                         double infeasibility = CoinMax(fullSolution[iRow] - rowUpper[iRow],
                                                        rowLower[iRow] - fullSolution[iRow]);
                         weight[iRow] = -infeasibility;
                         if (infeasibility > 1.0e-8) {
                              numberInfeasibilities++;
                              sumInfeasibilities += infeasibility;
                         }
                    }
               }
               // sort
               CoinSort_2(weight, weight + originalNumberRows, sort);
               numberSort = CoinMin(originalNumberRows, smallNumberRows + numberKept);
               memset(take, 0, originalNumberRows);
               for (iRow = 0; iRow < numberSort; iRow++)
                    take[sort[iRow]] = 1;
               numberSmallColumns = 0;
               for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                    int n = 0;
                    for (int j = start[iColumn]; j < start[iColumn] + length[iColumn]; j++) {
                         int iRow = row[j];
                         if (take[iRow])
                              n++;
                    }
                    if (n)
                         whichColumns[numberSmallColumns++] = iColumn;
               }
               printf("%d rows binding, %d rows kept, %d rows dropped - new size %d rows, %d columns\n",
                      numberBinding, numberKept, numberDropped, numberSort, numberSmallColumns);
               printf("%d rows are infeasible - sum is %g\n", numberInfeasibilities,
                      sumInfeasibilities);
               if (!numberInfeasibilities) {
                    printf("Exiting as looks optimal\n");
                    break;
               }
               numberInfeasibilities = 0;
               sumInfeasibilities = 0.0;
               for (iSort = 0; iSort < numberSort; iSort++) {
                    if (weight[iSort] > -1.0e30 && weight[iSort] < -1.0e-8) {
                         numberInfeasibilities++;
                         sumInfeasibilities += -weight[iSort];
                    }
               }
               printf("in small model %d rows are infeasible - sum is %g\n", numberInfeasibilities,
                      sumInfeasibilities);
          }
     }
     delete [] weight;
     delete [] sort;
     delete [] whichColumns;
     delete [] take;
     // If problem is big you may wish to skip this
     model2->dual();
     int numberBinding = 0;
     for (iRow = 0; iRow < originalNumberRows; iRow++) {
          if (model2->getRowStatus(iRow) != ClpSimplex::basic)
               numberBinding++;
     }
     printf("%d binding rows at end\n", numberBinding);
     pinfo.postsolve(true);

     int numberIterations = model2->numberIterations();;
     delete model2;
     /* After this postsolve model should be optimal.
        We can use checkSolution and test feasibility */
     model.checkSolution();
     if (model.numberDualInfeasibilities() ||
               model.numberPrimalInfeasibilities())
          printf("%g dual %g(%d) Primal %g(%d)\n",
                 model.objectiveValue(),
                 model.sumDualInfeasibilities(),
                 model.numberDualInfeasibilities(),
                 model.sumPrimalInfeasibilities(),
                 model.numberPrimalInfeasibilities());
     // But resolve for safety
     model.primal(1);

     numberIterations += model.numberIterations();;
     printf("Solve took %g seconds\n", CoinCpuTime() - time1);
     return 0;
}
Exemple #3
0
int main(int argc, const char *argv[])
{
     ClpSimplex  model;
     int status;
     // Keep names
     if (argc < 2) {
          status = model.readMps("small.mps", true);
     } else {
          status = model.readMps(argv[1], true);
     }
     if (status)
          exit(10);
     /*
       This driver turns a problem into all equalities, solves it and
       then creates optimal basis.
     */

     // copy of original
     ClpSimplex model2(model);
     // And another
     ClpSimplex model3(model);

     int originalNumberColumns = model.numberColumns();
     int numberRows = model.numberRows();

     int * addStarts = new int [numberRows+1];
     int * addRow = new int[numberRows];
     double * addElement = new double[numberRows];
     double * newUpper = new double[numberRows];
     double * newLower = new double[numberRows];

     double * lower = model2.rowLower();
     double * upper = model2.rowUpper();
     int iRow;
     // Simplest is to change all rhs to zero
     // One should skip E rows but this is simpler coding
     for (iRow = 0; iRow < numberRows; iRow++) {
          newUpper[iRow] = upper[iRow];
          upper[iRow] = 0.0;
          newLower[iRow] = lower[iRow];
          lower[iRow] = 0.0;
          addRow[iRow] = iRow;
          addElement[iRow] = -1.0;
          addStarts[iRow] = iRow;
     }
     addStarts[numberRows] = numberRows;
     model2.addColumns(numberRows, newLower, newUpper, NULL,
                       addStarts, addRow, addElement);
     delete [] addStarts;
     delete [] addRow;
     delete [] addElement;
     delete [] newLower;
     delete [] newUpper;

     // Modify costs
     double * randomArray = new double[numberRows];
     for (iRow = 0; iRow < numberRows; iRow++)
          randomArray[iRow] = CoinDrand48();

     model2.transposeTimes(1.0, randomArray, model2.objective());
     delete [] randomArray;
     // solve
     model2.primal();
     // first check okay if solution values back
     memcpy(model.primalColumnSolution(), model2.primalColumnSolution(),
            originalNumberColumns * sizeof(double));
     memcpy(model.primalRowSolution(), model2.primalRowSolution(),
            numberRows * sizeof(double));
     int iColumn;
     for (iColumn = 0; iColumn < originalNumberColumns; iColumn++)
          model.setColumnStatus(iColumn, model2.getColumnStatus(iColumn));

     for (iRow = 0; iRow < numberRows; iRow++) {
          if (model2.getRowStatus(iRow) == ClpSimplex::basic) {
               model.setRowStatus(iRow, ClpSimplex::basic);
          } else {
               model.setRowStatus(iRow, model2.getColumnStatus(iRow + originalNumberColumns));
          }
     }
     model.primal(0);
     // and now without solution values

     for (iColumn = 0; iColumn < originalNumberColumns; iColumn++)
          model3.setColumnStatus(iColumn, model2.getColumnStatus(iColumn));

     for (iRow = 0; iRow < numberRows; iRow++)
          model3.setRowStatus(iRow, model2.getColumnStatus(iRow + originalNumberColumns));
     model3.primal(0);
     return 0;
}
/*
  Randomized Rounding Heuristic
  Returns 1 if solution, 0 if not
*/
int
CbcHeuristicRandRound::solution(double & solutionValue,
                                double * betterSolution)
{
    // rlh: Todo: Memory Cleanup

    //  std::cout << "Entering the Randomized Rounding Heuristic" << std::endl;

    setWhen(1);  // setWhen(1) didn't have the effect I expected (e.g., run once).

    // Run only once.
    //
    //    See if at root node
    bool atRoot = model_->getNodeCount() == 0;
    int passNumber = model_->getCurrentPassNumber();
    //    Just do once
    if (!atRoot || passNumber > 1) {
        // std::cout << "Leaving the Randomized Rounding Heuristic" << std::endl;
        return 0;
    }

    std::cout << "Entering the Randomized Rounding Heuristic" << std::endl;
    typedef struct {
        int numberSolutions;
        int maximumSolutions;
        int numberColumns;
        double ** solution;
        int * numberUnsatisfied;
    } clpSolution;

    double start = CoinCpuTime();
    numCouldRun_++; //
#ifdef HEURISTIC_INFORM
    printf("Entering heuristic %s - nRuns %d numCould %d when %d\n",
	   heuristicName(),numRuns_,numCouldRun_,when_);
#endif
    // Todo: Ask JJHF what "number of times
    // the heuristic could run" means.

    OsiSolverInterface * solver = model_->solver()->clone();
    double primalTolerance ;
    solver->getDblParam(OsiPrimalTolerance, primalTolerance) ;
    OsiClpSolverInterface * clpSolver = dynamic_cast<OsiClpSolverInterface *> (solver);
    assert (clpSolver);
    ClpSimplex * simplex = clpSolver->getModelPtr();

    // Initialize the structure holding the solutions for the Simplex iterations
    clpSolution solutions;
    // Set typeStruct field of ClpTrustedData struct to 1 to indicate
    // desired behavior for  RandRound heuristic (which is what?)
    ClpTrustedData trustedSolutions;
    trustedSolutions.typeStruct = 1;
    trustedSolutions.data = &solutions;
    solutions.numberSolutions = 0;
    solutions.maximumSolutions = 0;
    solutions.numberColumns = simplex->numberColumns();
    solutions.solution = NULL;
    solutions.numberUnsatisfied = NULL;
    simplex->setTrustedUserPointer(&trustedSolutions);

    // Solve from all slack to get some points
    simplex->allSlackBasis();

    // Calling primal() invalidates pointers to some rim vectors,
    // like...row sense (!)
    simplex->primal();

    // 1. Okay - so a workaround would be to copy the data I want BEFORE
    // calling primal.
    // 2. Another approach is to ask the simplex solvers NOT to mess up my
    // rims.
    // 3. See freeCachedResults() for what is getting
    // deleted. Everything else points into the structure.
    // ...or use collower and colupper rather than rowsense.
    // ..store address of where one of these

    // Store the basic problem information
    // -Get the number of columns, rows and rhs vector
    int numCols = clpSolver->getNumCols();
    int numRows = clpSolver->getNumRows();

    // Find the integer variables (use columnType(?))
    // One if not continuous, that is binary or general integer)
    // columnType() = 0 continuous
    //              = 1 binary
    //              = 2 general integer
    bool * varClassInt = new bool[numCols];
    const char* columnType = clpSolver->columnType();
    int numGenInt = 0;
    for (int i = 0; i < numCols; i++) {
        if (clpSolver->isContinuous(i))
            varClassInt[i] = 0;
        else
            varClassInt[i] = 1;
        if (columnType[i] == 2) numGenInt++;
    }

    // Heuristic is for problems with general integer variables.
    // If there are none, quit.
    if (numGenInt++ < 1) {
        delete [] varClassInt ;
        std::cout << "Leaving the Randomized Rounding Heuristic" << std::endl;
        return 0;
    }


    // -Get the rows sense
    const char * rowSense;
    rowSense = clpSolver->getRowSense();

    // -Get the objective coefficients
    double *originalObjCoeff = CoinCopyOfArray(clpSolver->getObjCoefficients(), numCols);

    // -Get the matrix of the problem
    // rlh: look at using sparse representation
    double ** matrix = new double * [numRows];
    for (int i = 0; i < numRows; i++) {
        matrix[i] = new double[numCols];
        for (int j = 0; j < numCols; j++)
            matrix[i][j] = 0;
    }

    const CoinPackedMatrix* matrixByRow = clpSolver->getMatrixByRow();
    const double * matrixElements = matrixByRow->getElements();
    const int * matrixIndices = matrixByRow->getIndices();
    const int * matrixStarts = matrixByRow->getVectorStarts();
    for (int j = 0; j < numRows; j++) {
        for (int i = matrixStarts[j]; i < matrixStarts[j+1]; i++) {
            matrix[j][matrixIndices[i]] = matrixElements[i];
        }
    }

    double * newObj = new double [numCols];
    srand ( static_cast<unsigned int>(time(NULL) + 1));
    int randNum;

    // Shuffle the rows:
    // Put the rows in a random order
    // so that the optimal solution is a different corner point than the
    // starting point.
    int * index = new int [numRows];
    for (int i = 0; i < numRows; i++)
        index[i] = i;
    for (int i = 0; i < numRows; i++) {
        int temp = index[i];
        int randNumTemp = i + intRand(numRows - i);
        index[i] = index[randNumTemp];
        index[randNumTemp] = temp;
    }

    // Start finding corner points by iteratively doing the following:
    // - contruct a randomly tilted objective
    // - solve
    for (int i = 0; i < numRows; i++) {
        // TODO: that 10,000 could be a param in the member data
        if (solutions.numberSolutions  > 10000)
            break;
        randNum = intRand(2);
        for (int j = 0; j < numCols; j++) {
            // for row i and column j vary the coefficient "a bit"
            if (randNum == 1)
                // if the element is zero, then set the new obj
                // coefficient to 0.1 (i.e., round up)
                if (fabs(matrix[index[i]][j]) < primalTolerance)
                    newObj[j] = 0.1;
                else
                    // if the element is nonzero, then increase the new obj
                    // coefficient "a bit"
                    newObj[j] = matrix[index[i]][j] * 1.1;
            else
                // if randnum is 2, then
                // if the element is zero, then set the new obj coeffient
                // to NEGATIVE 0.1 (i.e., round down)
                if (fabs(matrix[index[i]][j]) < primalTolerance)
                    newObj[j] = -0.1;
                else
                    // if the element is nonzero, then DEcrease the new obj coeffienct "a bit"
                    newObj[j] = matrix[index[i]][j] * 0.9;
        }
        // Use the new "tilted" objective
        clpSolver->setObjective(newObj);

        // Based on the row sense, we decide whether to max or min
        if (rowSense[i] == 'L')
            clpSolver->setObjSense(-1);
        else
            clpSolver->setObjSense(1);

        // Solve with primal simplex
        simplex->primal(1);
        // rlh+ll: This was the original code. But we already have the
        // model pointer (it's in simplex). And, calling getModelPtr()
        // invalidates the cached data in the OsiClpSolverInterface
        // object, which means our precious rowsens is lost. So let's
        // not use the line below...
        /******* clpSolver->getModelPtr()->primal(1); */
        printf("---------------------------------------------------------------- %d\n", i);
    }
    // Iteratively do this process until...
    // either you reach the max number of corner points (aka 10K)
    // or all the rows have been used as an objective.

    // Look at solutions
    int numberSolutions = solutions.numberSolutions;
    //const char * integerInfo = simplex->integerInformation();
    //const double * columnLower = simplex->columnLower();
    //const double * columnUpper = simplex->columnUpper();
    printf("there are %d solutions\n", numberSolutions);

    // Up to here we have all the corner points
    // Now we need to do the random walks and roundings

    double ** cornerPoints = new double * [numberSolutions];
    for (int j = 0; j < numberSolutions; j++)
        cornerPoints[j] = solutions.solution[j];

    bool feasibility = 1;
    // rlh: use some COIN max instead of 1e30 (?)
    double bestObj = 1e30;
    std::vector< std::vector <double> > feasibles;
    int numFeasibles = 0;

    // Check the feasibility of the corner points
    int numCornerPoints = numberSolutions;

    const double * rhs = clpSolver->getRightHandSide();
    // rlh: row sense hasn't changed. why a fresh copy?
    // Delete next line.
    rowSense = clpSolver->getRowSense();

    for (int i = 0; i < numCornerPoints; i++) {
        //get the objective value for this this point
        double objValue = 0;
        for (int k = 0; k < numCols; k++)
            objValue += cornerPoints[i][k] * originalObjCoeff[k];

        if (objValue < bestObj) {
            // check integer feasibility
            feasibility = 1;
            for (int j = 0; j < numCols; j++) {
                if (varClassInt[j]) {
                    double closest = floor(cornerPoints[i][j] + 0.5);
                    if (fabs(cornerPoints[i][j] - closest) > primalTolerance) {
                        feasibility = 0;
                        break;
                    }
                }
            }
            // check all constraints satisfied
            if (feasibility) {
                for (int irow = 0; irow < numRows; irow++) {
                    double lhs = 0;
                    for (int j = 0; j < numCols; j++) {
                        lhs += matrix[irow][j] * cornerPoints[i][j];
                    }
                    if (rowSense[irow] == 'L' && lhs > rhs[irow] + primalTolerance) {
                        feasibility = 0;
                        break;
                    }
                    if (rowSense[irow] == 'G' && lhs < rhs[irow] - primalTolerance) {
                        feasibility = 0;
                        break;
                    }
                    if (rowSense[irow] == 'E' && (lhs - rhs[irow] > primalTolerance || lhs - rhs[irow] < -primalTolerance)) {
                        feasibility = 0;
                        break;
                    }
                }
            }

            if (feasibility) {
                numFeasibles++;
                feasibles.push_back(std::vector <double> (numCols));
                for (int k = 0; k < numCols; k++)
                    feasibles[numFeasibles-1][k] = cornerPoints[i][k];
                printf("obj: %f\n", objValue);
                if (objValue < bestObj)
                    bestObj = objValue;
            }
        }
    }
    int numFeasibleCorners;
    numFeasibleCorners = numFeasibles;
    //find the center of gravity of the corner points as the first random point
    double * rp = new double[numCols];
    for (int i = 0; i < numCols; i++) {
        rp[i] = 0;
        for (int j = 0; j < numCornerPoints; j++) {
            rp[i] += cornerPoints[j][i];
        }
        rp[i] = rp[i] / numCornerPoints;
    }

    //-------------------------------------------
    //main loop:
    // -generate the next random point
    // -round the random point
    // -check the feasibility of the random point
    //-------------------------------------------

    srand ( static_cast<unsigned int>(time(NULL) + 1));
    int numRandomPoints = 0;
    while (numRandomPoints < 50000) {
        numRandomPoints++;
        //generate the next random point
        int randomIndex = intRand(numCornerPoints);
        double random = CoinDrand48();
        for (int i = 0; i < numCols; i++) {
            rp[i] = (random * (cornerPoints[randomIndex][i] - rp[i])) + rp[i];
        }

        //CRISP ROUNDING
        //round the random point just generated
        double * roundRp = new double[numCols];
        for (int i = 0; i < numCols; i++) {
            roundRp[i] = rp[i];
            if (varClassInt[i]) {
                if (rp[i] >= 0) {
                    if (fmod(rp[i], 1) > 0.5)
                        roundRp[i] = floor(rp[i]) + 1;
                    else
                        roundRp[i] = floor(rp[i]);
                } else {
                    if (fabs(fmod(rp[i], 1)) > 0.5)
                        roundRp[i] = floor(rp[i]);
                    else
                        roundRp[i] = floor(rp[i]) + 1;

                }
            }
        }


        //SOFT ROUNDING
        // Look at original files for the "how to" on soft rounding;
        // Soft rounding omitted here.

        //Check the feasibility of the rounded random point
        // -Check the feasibility
        // -Get the rows sense
        rowSense = clpSolver->getRowSense();
        rhs = clpSolver->getRightHandSide();

        //get the objective value for this feasible point
        double objValue = 0;
        for (int i = 0; i < numCols; i++)
            objValue += roundRp[i] * originalObjCoeff[i];

        if (objValue < bestObj) {
            feasibility = 1;
            for (int i = 0; i < numRows; i++) {
                double lhs = 0;
                for (int j = 0; j < numCols; j++) {
                    lhs += matrix[i][j] * roundRp[j];
                }
                if (rowSense[i] == 'L' && lhs > rhs[i] + primalTolerance) {
                    feasibility = 0;
                    break;
                }
                if (rowSense[i] == 'G' && lhs < rhs[i] - primalTolerance) {
                    feasibility = 0;
                    break;
                }
                if (rowSense[i] == 'E' && (lhs - rhs[i] > primalTolerance || lhs - rhs[i] < -primalTolerance)) {
                    feasibility = 0;
                    break;
                }
            }
            if (feasibility) {
                printf("Feasible Found.\n");
                printf("%.2f\n", CoinCpuTime() - start);
                numFeasibles++;
                feasibles.push_back(std::vector <double> (numCols));
                for (int i = 0; i < numCols; i++)
                    feasibles[numFeasibles-1][i] = roundRp[i];
                printf("obj: %f\n", objValue);
                if (objValue < bestObj)
                    bestObj = objValue;
            }
        }
        delete [] roundRp;
    }
    printf("Number of Feasible Corners: %d\n", numFeasibleCorners);
    printf("Number of Feasibles Found: %d\n", numFeasibles);
    if (numFeasibles > 0)
        printf("Best Objective: %f\n", bestObj);
    printf("time: %.2f\n", CoinCpuTime() - start);

    if (numFeasibles == 0) {
        // cleanup
        delete [] varClassInt;
        for (int i = 0; i < numRows; i++)
            delete matrix[i];
        delete [] matrix;
        delete [] newObj;
        delete [] index;
        for (int i = 0; i < numberSolutions; i++)
            delete cornerPoints[i];
        delete [] cornerPoints;
        delete [] rp;
        return 0;
    }

    // We found something better
    solutionValue = bestObj;
    for (int k = 0; k < numCols; k++) {
        betterSolution[k] =  feasibles[numFeasibles-1][k];
    }
    delete [] varClassInt;
    for (int i = 0; i < numRows; i++)
        delete matrix[i];
    delete [] matrix;
    delete [] newObj;
    delete [] index;
    for (int i = 0; i < numberSolutions; i++)
        delete cornerPoints[i];
    delete [] cornerPoints;
    delete [] rp;
    std::cout << "Leaving the Randomized Rounding Heuristic" << std::endl;
    return 1;

}
static inline int intRand(const int range)
{
    return static_cast<int> (floor(CoinDrand48() * range));
}
void CglOddHole::generateCuts(const OsiRowCutDebugger * /*debugger*/,
			      const CoinPackedMatrix & rowCopy, 
				 const double * solution, 
			      const double * dj, OsiCuts & cs,
				 const int * suitableRow,
			      const int * fixedColumn,
			      const CglTreeInfo info,
			      bool packed)
{
  CoinPackedMatrix columnCopy = rowCopy;
  columnCopy.reverseOrdering();

  // Get basic problem information
  int nRows=columnCopy.getNumRows(); 
  int nCols=columnCopy.getNumCols(); 
  
  const int * column = rowCopy.getIndices();
  const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
  const int * rowLength = rowCopy.getVectorLengths(); 
  
  const int * row = columnCopy.getIndices();
  const CoinBigIndex * columnStart = columnCopy.getVectorStarts();
  const int * columnLength = columnCopy.getVectorLengths(); 

  // we need only look at suitable rows and variables with unsatisfied 0-1
  // lookup from true row to compressed matrix
  int * mrow = new int[nRows];
  // lookup from true column to compressed
  int * lookup = new int[nCols];
  // number of columns in compressed matrix
  int nSmall=0;
  int i;
  //do lookup from true sequence to compressed
  int n=0;
  for (i=0;i<nRows;i++) {
    if (suitableRow[i]>0) {
      mrow[i]=n++;
    } else {
      mrow[i]=-1;
    }
  }
  for (i=0;i<nCols;i++) {
    if (!fixedColumn[i]) {
      lookup[i]=nSmall++;
    } else {
      lookup[i]=-1;
    }
  }
  int nSmall2=2*nSmall;
  // we don't know how big matrix will be
#define MAXELS 50000
  int maxels=MAXELS;
  //How do I do reallocs in C++?
  // 1.0 - value x(i) - value x(j) for each node pair (or reverse if cover) 
  double * cost = reinterpret_cast<double *> (malloc(maxels*sizeof(double)));
  // arc i.e. j which can be reached from i
  int * to= reinterpret_cast<int *> (malloc(maxels*sizeof(int)));
  //original row for each arc
  int * rowfound=reinterpret_cast<int *> (malloc(maxels*sizeof(int)));
  // start of each column
  int * starts=new int[2*nSmall+1];
  starts[0]=0;
  // useful array for marking if already connected
  int * mark =new int[nSmall2];
  memset(mark,0,nSmall2*sizeof(int));
  n=0; //number of elements in matrix
  for (i=0;i<nCols;i++) {
    int icol=lookup[i];
    if (icol>=0) {
      // column in compressed matrix
      int k;
      double dd=1.0000001-solution[i];
      mark[icol]=1;
      // reallocate if matrix reached size limit
      if (n+nCols>maxels) {
	maxels*=2;
	cost=reinterpret_cast<double *> (realloc(cost,maxels*sizeof(double)));
	to=reinterpret_cast<int *> (realloc(to,maxels*sizeof(int)));
	rowfound=reinterpret_cast<int *> (realloc(rowfound,maxels*sizeof(int)));
      }
      // get all other connected variables
      for (k=columnStart[i];k<columnStart[i]+columnLength[i];k++) {
	int irow=row[k];
	int jrow=mrow[irow];
	// but only if row in compressed matrix
	if (jrow>=0) {
	  int j;
	  for (j=rowStart[irow];j<rowStart[irow]+rowLength[irow];j++) {
	    int jcol=column[j];
	    int kcol=lookup[jcol];
	    if (kcol>=0&&!mark[kcol]) {
	      cost[n]=dd-solution[jcol];
	      to[n]=kcol;
	      rowfound[n++]=irow;//original row
	      mark[kcol]=1;
	    }
	  }
	}
      }
      starts[icol+1]=n;
      // zero out markers for next column
      mark[icol]=0;
      for (k=starts[icol];k<starts[icol+1];k++) {
	int ito=to[k];
	if (ito<0||ito>=nSmall) abort();
	mark[to[k]]=0;
      }
    }
  }
  //if cover then change sign - otherwise make sure positive
  if (packed) {
    for (i=0;i<n;i++) {
      if (cost[i]<1.0e-10) {
	cost[i]=1.0e-10;
      }
    }
  } else {
    for (i=0;i<n;i++) {
      cost[i]=-cost[i];
      if (cost[i]<1.0e-10) {
	cost[i]=1.0e-10;
      }
    }
  }
  // we are going to double size 

  if (2*n>maxels) {
    maxels=2*n;
    cost=reinterpret_cast<double *> (realloc(cost,maxels*sizeof(double)));
    to=reinterpret_cast<int *> (realloc(to,maxels*sizeof(int)));
    rowfound=reinterpret_cast<int *> (realloc(rowfound,maxels*sizeof(int)));
  }
  /* copy and make bipartite*/

  for (i=0;i<nSmall;i++) {
    int k,j=i+nSmall;
    for (k=starts[i];k<starts[i+1];k++) {
      int ito=to[k];
      to[n]=ito;
      to[k]=ito+nSmall;
      cost[n]=cost[k];
      rowfound[n++]=rowfound[k];;
    }
    starts[j+1]=n;
  }
  //random numbers to winnow out duplicate cuts
  double * check = new double[nCols];
  if (info.randomNumberGenerator) {
    const CoinThreadRandom * randomGenerator = info.randomNumberGenerator;
    for (i=0;i<nCols;i++) {
      check[i]=randomGenerator->randomDouble();
    }
  } else {
    CoinSeedRandom(13579);
    for (i=0;i<nCols;i++) {
      check[i]=CoinDrand48(); // NOT on a thread by thread basis
    }
  }

  // Shortest path algorithm from Dijkstra - is there a better one?

  typedef struct {
    double cost; //cost to starting node
    int back; //previous node
  } Path;
  typedef struct {
    double cost; //cost to starting node
    int node; //node
  } Item;
  Item * stack = new Item [nSmall2];
  Path * path = new Path [nSmall2];
  // arrays below are used only if looks promising
  // allocate here
  // we don't know how many cuts will be generated
  int ncuts=0;
  int maxcuts=1000;
  double * hash = reinterpret_cast<double *> (malloc(maxcuts*sizeof(double)));
  // to clean (should not be needed)
  int * clean = new int[nSmall2];
  int * candidate = new int[CoinMax(nSmall2,nCols)];
  double * element = new double[nCols];
  // in case we want to sort
  double_double_int_triple * sortit = 
    new double_double_int_triple [nCols];
  memset(mark,0,nSmall2*sizeof(int));
  int * countcol = new int[nCols];
  memset(countcol,0,nCols*sizeof(int));
  int bias = packed ? 0 : 1; //amount to add before halving
  // If nSmall large then should do a randomized subset
  // Improvement 1
  int icol;
  for (icol=0;icol<nSmall;icol++) {
    int j;
    int jcol=icol+nSmall;
    int istack=1;
    for (j=0;j<nSmall2;j++) {
      path[j].cost=1.0e70;
      path[j].back=nSmall2+1;
    }
    path[icol].cost=0.0;
    path[icol].back=-1;
    stack[0].cost=0.0;
    stack[0].node=icol;
    mark[icol]=1;
    while(istack) {
      Item thisItem=stack[--istack];
      double thisCost=thisItem.cost;
      int inode=thisItem.node;
      int k;
      mark[inode]=0; //say available for further work
      // See if sorting every so many would help (and which way)?
      // Improvement 2
      for (k=starts[inode];k<starts[inode+1];k++) {
	int jnode=to[k];
	if (!mark[jnode]&&thisCost+cost[k]<path[jnode].cost-1.0e-12) {
	  path[jnode].cost=thisCost+cost[k];
	  path[jnode].back=inode;
	  // add to stack
	  stack[istack].cost=path[jnode].cost;
	  stack[istack++].node=jnode;
	  mark[jnode]=1;
#ifdef CGL_DEBUG
	  assert (istack<=nSmall2);
#endif
	}
      }
    }
    bool good=(path[jcol].cost<0.9999);

    if (good)  { /* try */
      int ii;
      int nrow2=0;
      int nclean=0;
      double sum=0;
#ifdef CGL_DEBUG
      printf("** %d ",jcol-nSmall);
#endif
      ii=1;
      candidate[0]=jcol;
      while(jcol!=icol) {
	int jjcol;
	jcol=path[jcol].back;
	if (jcol>=nSmall) {
	  jjcol=jcol-nSmall;
	} else {
	  jjcol=jcol;
	}
#ifdef CGL_DEBUG
	printf(" %d",jjcol);
#endif
	if (mark[jjcol]) {
	  // good=false;
	  // probably means this is from another cycle (will have been found)
	  // one of cycles must be zero cost
	  // printf("variable already on chain!\n");
	} else {
	  mark[jjcol]=1;
	  clean[nclean++]=jjcol;
	  candidate[ii++]=jcol;
#ifdef CGL_DEBUG
	  assert (ii<=nSmall2);
#endif
	}
      }
#ifdef CGL_DEBUG
      printf("\n");
#endif
      for (j=0;j<nclean;j++) {
	int k=clean[j];
	mark[k]=0;
      }
      if (good) {
	int k;
	for (k=ii-1;k>0;k--) {
	  int jk,kk=candidate[k];
	  int ix=0;
	  for (jk=starts[kk];jk<starts[kk+1];jk++) {
	    int ito=to[jk];
	    if (ito==candidate[k-1]) {
	      ix=1;
	      // back to original row
	      mrow[nrow2++]=rowfound[jk];
	      break;
	    }
	  }
	  if (!ix) {
	    good=false;
	  }
	}
	if ((nrow2&1)!=1) {
	  good=false;
	}
	if (good) {
	  int nincut=0;
	  for (k=0;k<nrow2;k++) {
	    int j,irow=mrow[k];
	    for (j=rowStart[irow];j<rowStart[irow]+rowLength[irow];j++) {
	      int icol=column[j];
	      if (!countcol[icol]) candidate[nincut++]=icol;
	      countcol[icol]++;
	    }
	  }
#ifdef CGL_DEBUG
	  printf("true constraint %d",nrow2);
#endif
	  nrow2=nrow2>>1;
	  double rhs=nrow2; 
	  if (!packed) rhs++; // +1 for cover
	  ii=0;
	  for (k=0;k<nincut;k++) {
	    int jcol=candidate[k];
	    if (countcol[jcol]) {
#ifdef CGL_DEBUG
	      printf(" %d %d",jcol,countcol[jcol]);
#endif
	      int ihalf=(countcol[jcol]+bias)>>1;
	      if (ihalf) {
		element[ii]=ihalf;
		sum+=solution[jcol]*element[ii];
		/*printf("%d %g %g\n",jcol,element[ii],sumall[jcol]);*/
		candidate[ii++]=jcol;
	      }
	      countcol[jcol]=0;
	    }
	  }
#ifdef CGL_DEBUG
          printf("\n");
#endif
	  OsiRowCut rc;
	  double violation=0.0;
	  if (packed) {
	    violation = sum-rhs;
	    rc.setLb(-COIN_DBL_MAX);
	    rc.setUb(rhs);   
	  } else {
	    // other way for cover
	    violation = rhs-sum;
	    rc.setUb(COIN_DBL_MAX);
	    rc.setLb(rhs);   
	  }
	  if (violation<minimumViolation_) {
#ifdef CGL_DEBUG
	    printf("why no cut\n");
#endif
	    good=false;
	  } else {
	    if (static_cast<double> (ii) * minimumViolationPer_>violation||
		ii>maximumEntries_) {
#ifdef CGL_DEBUG
	      printf("why no cut\n");
#endif
	      if (packed) {
		// sort and see if we can get down to length
		// relax by taking out ones with solution 0.0
		nincut=ii;
		for (k=0;k<nincut;k++) {
		  int jcol=candidate[k];
		  double value = fabs(dj[jcol]);
		  if (solution[jcol])
		  value = -solution[jcol];
		  sortit[k].dj=value;
		  sortit[k].element=element[k];
		  sortit[k].sequence=jcol;
		}
		// sort 
		std::sort(sortit,sortit+nincut,double_double_int_triple_compare());
		nincut = CoinMin(nincut,maximumEntries_);
		sum=0.0;
		for (k=0;k<nincut;k++) {
		  int jcol=sortit[k].sequence;
		  candidate[k]=jcol;
		  element[k]=sortit[k].element;
		  sum+=solution[jcol]*element[k];
		}
		violation = sum-rhs;
		ii=nincut;
		if (violation<minimumViolation_) {
		  good=false;
		}
	      } else { 
		good=false;
	      }
	    }
	  }
	  if (good) {
	    //this assumes not many cuts
	    int j;
#if 0
	    double value=0.0;
	    for (j=0;j<ii;j++) {
	      int icol=candidate[j];
	      value += check[icol]*element[j];
	    }
#else
            CoinPackedVector candidatePv(ii,candidate,element);
            candidatePv.sortIncrIndex();
            double value = candidatePv.dotProduct(check);
#endif

	    for (j=0;j<ncuts;j++) {
	      if (value==hash[j]) {
		//could check equality - quicker just to assume
		break;
	      }
	    }
	    if (j==ncuts) {
	      //new
	      if (ncuts==maxcuts) {
		maxcuts *= 2;
		hash = reinterpret_cast<double *> (realloc(hash,maxcuts*sizeof(double)));
	      }
	      hash[ncuts++]=value;
	      rc.setRow(ii,candidate,element);
#ifdef CGL_DEBUG
	      printf("sum %g rhs %g %d\n",sum,rhs,ii);
	      if (debugger) 
		assert(!debugger->invalidCut(rc)); 
#endif
	      cs.insert(rc);
	    }
	  }
	}
	/* end of adding cut */
      }
    }
  }
  delete [] countcol;
  delete [] element;
  delete [] candidate;
  delete [] sortit;
  delete [] clean;
  delete [] path;
  delete [] stack;
  free(hash);
  delete [] check;
  delete [] mark;
  delete [] starts;
  delete [] lookup;
  delete [] mrow;
  free(rowfound);
  free(to);
  free(cost);
}
//--------------------------------------------------------------------------
// Test building a model
void
CoinModelUnitTest(const std::string & mpsDir,
                  const std::string & netlibDir, const std::string & testModel)
{

    // Get a model
    CoinMpsIO m;
    std::string fn = mpsDir+"exmip1";
    int numErr = m.readMps(fn.c_str(),"mps");
    assert( numErr== 0 );

    int numberRows = m.getNumRows();
    int numberColumns = m.getNumCols();

    // Build by row from scratch
    {
        CoinPackedMatrix matrixByRow = * m.getMatrixByRow();
        const double * element = matrixByRow.getElements();
        const int * column = matrixByRow.getIndices();
        const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
        const int * rowLength = matrixByRow.getVectorLengths();
        const double * rowLower = m.getRowLower();
        const double * rowUpper = m.getRowUpper();
        const double * columnLower = m.getColLower();
        const double * columnUpper = m.getColUpper();
        const double * objective = m.getObjCoefficients();
        int i;
        CoinModel temp;
        for (i=0; i<numberRows; i++) {
            temp.addRow(rowLength[i],column+rowStart[i],
                        element+rowStart[i],rowLower[i],rowUpper[i],m.rowName(i));
        }
        // Now do column part
        for (i=0; i<numberColumns; i++) {
            temp.setColumnBounds(i,columnLower[i],columnUpper[i]);
            temp.setColumnObjective(i,objective[i]);
            if (m.isInteger(i))
                temp.setColumnIsInteger(i,true);;
        }
        // write out
        temp.writeMps("byRow.mps");
    }

    // Build by column from scratch and save
    CoinModel model;
    {
        CoinPackedMatrix matrixByColumn = * m.getMatrixByCol();
        const double * element = matrixByColumn.getElements();
        const int * row = matrixByColumn.getIndices();
        const CoinBigIndex * columnStart = matrixByColumn.getVectorStarts();
        const int * columnLength = matrixByColumn.getVectorLengths();
        const double * rowLower = m.getRowLower();
        const double * rowUpper = m.getRowUpper();
        const double * columnLower = m.getColLower();
        const double * columnUpper = m.getColUpper();
        const double * objective = m.getObjCoefficients();
        int i;
        for (i=0; i<numberColumns; i++) {
            model.addColumn(columnLength[i],row+columnStart[i],
                            element+columnStart[i],columnLower[i],columnUpper[i],
                            objective[i],m.columnName(i),m.isInteger(i));
        }
        // Now do row part
        for (i=0; i<numberRows; i++) {
            model.setRowBounds(i,rowLower[i],rowUpper[i]);
        }
        // write out
        model.writeMps("byColumn.mps");
    }

    // model was created by column - play around
    {
        CoinModel temp;
        int i;
        for (i=numberRows-1; i>=0; i--)
            temp.setRowLower(i,model.getRowLower(i));
        for (i=0; i<numberColumns; i++) {
            temp.setColumnUpper(i,model.getColumnUpper(i));
            temp.setColumnName(i,model.getColumnName(i));
        }
        for (i=numberColumns-1; i>=0; i--) {
            temp.setColumnLower(i,model.getColumnLower(i));
            temp.setColumnObjective(i,model.getColumnObjective(i));
            temp.setColumnIsInteger(i,model.getColumnIsInteger(i));
        }
        for (i=0; i<numberRows; i++) {
            temp.setRowUpper(i,model.getRowUpper(i));
            temp.setRowName(i,model.getRowName(i));
        }
        // Now elements
        for (i=0; i<numberRows; i++) {
            CoinModelLink triple=model.firstInRow(i);
            while (triple.column()>=0) {
                temp(i,triple.column(),triple.value());
                triple=model.next(triple);
            }
        }
        // and by column
        for (i=numberColumns-1; i>=0; i--) {
            CoinModelLink triple=model.lastInColumn(i);
            while (triple.row()>=0) {
                assert (triple.value()==temp(triple.row(),i));
                temp(triple.row(),i,triple.value());
                triple=model.previous(triple);
            }
        }
        // check equal
        model.setLogLevel(1);
        assert (!model.differentModel(temp,false));
    }
    // Try creating model with strings
    {
        CoinModel temp;
        int i;
        for (i=numberRows-1; i>=0; i--) {
            double value = model.getRowLower(i);
            if (value==-1.0)
                temp.setRowLower(i,"minusOne");
            else if (value==1.0)
                temp.setRowLower(i,"sqrt(plusOne)");
            else if (value==4.0)
                temp.setRowLower(i,"abs(4*plusOne)");
            else
                temp.setRowLower(i,value);
        }
        for (i=0; i<numberColumns; i++) {
            double value;
            value = model.getColumnUpper(i);
            if (value==-1.0)
                temp.setColumnUpper(i,"minusOne");
            else if (value==1.0)
                temp.setColumnUpper(i,"plusOne");
            else
                temp.setColumnUpper(i,value);
            temp.setColumnName(i,model.getColumnName(i));
        }
        for (i=numberColumns-1; i>=0; i--) {
            temp.setColumnLower(i,model.getColumnLower(i));
            temp.setColumnObjective(i,model.getColumnObjective(i));
            temp.setColumnIsInteger(i,model.getColumnIsInteger(i));
        }
        for (i=0; i<numberRows; i++) {
            double value = model.getRowUpper(i);
            if (value==-1.0)
                temp.setRowUpper(i,"minusOne");
            else if (value==1.0)
                temp.setRowUpper(i,"plusOne");
            else
                temp.setRowUpper(i,value);
            temp.setRowName(i,model.getRowName(i));
        }
        // Now elements
        for (i=0; i<numberRows; i++) {
            CoinModelLink triple=model.firstInRow(i);
            while (triple.column()>=0) {
                double value = triple.value();
                if (value==-1.0)
                    temp(i,triple.column(),"minusOne");
                else if (value==1.0)
                    temp(i,triple.column(),"plusOne");
                else if (value==-2.0)
                    temp(i,triple.column(),"minusOne-1.0");
                else if (value==2.0)
                    temp(i,triple.column(),"plusOne+1.0+minusOne+(2.0-plusOne)");
                else
                    temp(i,triple.column(),value);
                triple=model.next(triple);
            }
        }
        temp.associateElement("minusOne",-1.0);
        temp.associateElement("plusOne",1.0);
        temp.setProblemName("fromStrings");
        temp.writeMps("string.mps");

        // check equal
        model.setLogLevel(1);
        assert (!model.differentModel(temp,false));
    }
    // Test with various ways of generating
    {
        /*
          Get a model. Try first with netlibDir, fall back to mpsDir (sampleDir)
          if that fails.
        */
        CoinMpsIO m;
        std::string fn = netlibDir+testModel;
        double time1 = CoinCpuTime();
        int numErr = m.readMps(fn.c_str(),"");
        if (numErr != 0) {
            std::cout
                    << "Could not read " << testModel << " in " << netlibDir
                    << "; falling back to " << mpsDir << "." << std::endl ;
            fn = mpsDir+testModel ;
            numErr = m.readMps(fn.c_str(),"") ;
            if (numErr != 0) {
                std::cout << "Could not read " << testModel << "; skipping test." << std::endl ;
            }
        }
        if (numErr == 0) {
            std::cout
                    << "Time for readMps is "
                    << (CoinCpuTime()-time1) << " seconds." << std::endl ;
            int numberRows = m.getNumRows();
            int numberColumns = m.getNumCols();
            // Build model
            CoinModel model;
            CoinPackedMatrix matrixByRow = * m.getMatrixByRow();
            const double * element = matrixByRow.getElements();
            const int * column = matrixByRow.getIndices();
            const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
            const int * rowLength = matrixByRow.getVectorLengths();
            const double * rowLower = m.getRowLower();
            const double * rowUpper = m.getRowUpper();
            const double * columnLower = m.getColLower();
            const double * columnUpper = m.getColUpper();
            const double * objective = m.getObjCoefficients();
            int i;
            for (i=0; i<numberRows; i++) {
                model.addRow(rowLength[i],column+rowStart[i],
                             element+rowStart[i],rowLower[i],rowUpper[i],m.rowName(i));
            }
            // Now do column part
            for (i=0; i<numberColumns; i++) {
                model.setColumnBounds(i,columnLower[i],columnUpper[i]);
                model.setColumnObjective(i,objective[i]);
                model.setColumnName(i,m.columnName(i));
                if (m.isInteger(i))
                    model.setColumnIsInteger(i,true);;
            }
            // Test
            CoinSeedRandom(11111);
            time1 = 0.0;
            int nPass=50;
            for (i=0; i<nPass; i++) {
                double random = CoinDrand48();
                int iSeed = (int) (random*1000000);
                //iSeed = 776151;
                CoinSeedRandom(iSeed);
                std::cout << "before pass " << i << " with seed of " << iSeed << std::endl ;
                buildRandom(model,CoinDrand48(),time1,i);
                model.validateLinks();
            }
            std::cout
                    << "Time for " << nPass << " CoinModel passes is "
                    << time1 << " seconds\n" << std::endl ;
        }
    }
}
/* Build a model in some interesting way

   Nine blocks defined by 4 random numbers
   If next random number <0.4 addRow next possible
   If <0.8 addColumn if possible
   Otherwise do by element
   For each one use random <0.5 to add rim at same time
   At end fill in rim at random

*/
void buildRandom(CoinModel & baseModel, double random, double & timeIt, int iPass)
{
    CoinModel model;
    int numberRows = baseModel.numberRows();
    int numberColumns = baseModel.numberColumns();
    int numberElements = baseModel.numberElements();
    // Row numbers and column numbers
    int lastRow[4];
    int lastColumn[4];
    int i;
    lastRow[0]=0;
    lastColumn[0]=0;
    lastRow[3]=numberRows;
    lastColumn[3]=numberColumns;
    for ( i=1; i<3; i++) {
        int size;
        size = (int) ((0.25*random+0.2)*numberRows);
        random = CoinDrand48();
        lastRow[i]=lastRow[i-1]+size;
        size = (int) ((0.25*random+0.2)*numberColumns);
        random = CoinDrand48();
        lastColumn[i]=lastColumn[i-1]+size;
    }
    // whether block done 0 row first
    char block[9]= {0,0,0,0,0,0,0,0,0};
    // whether rowRim done
    char rowDone[3]= {0,0,0};
    // whether columnRim done
    char columnDone[3]= {0,0,0};
    // Save array for deleting elements
    CoinModelTriple * dTriple = new CoinModelTriple[numberElements];
    numberElements=0;
    double time1 = CoinCpuTime();
    for (int jBlock=0; jBlock<9; jBlock++) {
        int iType=-1;
        int iBlock=-1;
        if (random<0.4) {
            // trying addRow
            int j;
            for (j=0; j<3; j++) {
                int k;
                for (k=0; k<3; k++) {
                    if (block[3*j+k])
                        break; //already taken
                }
                if (k==3) {
                    // can do but decide which one
                    iBlock = 3*j + (int) (CoinDrand48()*0.3);
                    iType=0;
                    break;
                }
            }
        }
        if (iType==-1&&random<0.8) {
            // trying addRow
            int j;
            for (j=0; j<3; j++) {
                int k;
                for (k=0; k<3; k++) {
                    if (block[j+3*k])
                        break; //already taken
                }
                if (k==3) {
                    // can do but decide which one
                    iBlock = j + 3*((int) (CoinDrand48()*0.3));
                    iType=1;
                    break;
                }
            }
        }
        if (iType==-1) {
            iType=2;
            int j;
            for (j=0; j<9; j++) {
                if (!block[j]) {
                    iBlock=j;
                    break;
                }
            }
        }
        random=CoinDrand48();
        assert (iBlock>=0&&iBlock<9);
        assert (iType>=0);
        assert (!block[iBlock]);
        block[iBlock]=static_cast<char>(1+iType);
        int jRow = iBlock/3;
        int jColumn = iBlock%3;
        bool doRow = (CoinDrand48()<0.5)&&!rowDone[jRow];
        bool doColumn = (CoinDrand48()<0.5&&!columnDone[jColumn]);
        if (!iType) {
            // addRow
            int * column = new int[lastColumn[jColumn+1]-lastColumn[jColumn]];
            double * element = new double[lastColumn[jColumn+1]-lastColumn[jColumn]];
            for (i=lastRow[jRow]; i<lastRow[jRow+1]; i++) {
                int n=0;
                CoinModelLink triple=baseModel.firstInRow(i);
                while (triple.column()>=0) {
                    if (triple.column()>=lastColumn[jColumn]&&triple.column()<lastColumn[jColumn+1]) {
                        column[n]=triple.column();
                        element[n++]=triple.value();
                    }
                    triple=baseModel.next(triple);
                }
                assert (i>=model.numberRows());
                if (i>model.numberRows()) {
                    assert (i==lastRow[jRow]);
                    std::cout << "need to fill in rows" << std::endl ;
                    for (int k=0; k<jRow; k++) {
                        int start = CoinMax(lastRow[k],model.numberRows());
                        int end = lastRow[k+1];
                        bool doBounds = rowDone[k]!=0;
                        for (int j=start; j<end; j++) {
                            if (doBounds)
                                model.addRow(0,NULL,NULL,baseModel.rowLower(j),
                                             baseModel.rowUpper(j),baseModel.rowName(j));
                            else
                                model.addRow(0,NULL,NULL);
                        }
                    }
                }
                if (doRow)
                    model.addRow(n,column,element,baseModel.rowLower(i),
                                 baseModel.rowUpper(i),baseModel.rowName(i));
                else
                    model.addRow(n,column,element);
            }
            if (doRow) {
                rowDone[jRow]=1;
            }
            delete [] column;
            delete [] element;
        } else if (iType==1) {
            // addColumn
            int * row = new int[lastRow[jRow+1]-lastRow[jRow]];
            double * element = new double[lastRow[jRow+1]-lastRow[jRow]];
            for (i=lastColumn[jColumn]; i<lastColumn[jColumn+1]; i++) {
                int n=0;
                CoinModelLink triple=baseModel.firstInColumn(i);
                while (triple.row()>=0) {
                    if (triple.row()>=lastRow[jRow]&&triple.row()<lastRow[jRow+1]) {
                        row[n]=triple.row();
                        element[n++]=triple.value();
                    }
                    triple=baseModel.next(triple);
                }
                assert (i>=model.numberColumns());
                if (i>model.numberColumns()) {
                    assert (i==lastColumn[jColumn]);
                    std::cout << "need to fill in columns" << std::endl ;
                    for (int k=0; k<jColumn; k++) {
                        int start = CoinMax(lastColumn[k],model.numberColumns());
                        int end = lastColumn[k+1];
                        bool doBounds = columnDone[k]!=0;
                        for (int j=start; j<end; j++) {
                            if (doBounds)
                                model.addColumn(0,NULL,NULL,baseModel.columnLower(j),
                                                baseModel.columnUpper(j),baseModel.objective(j),
                                                baseModel.columnName(j),baseModel.isInteger(j));
                            else
                                model.addColumn(0,NULL,NULL);
                        }
                    }
                }
                if (doColumn)
                    model.addColumn(n,row,element,baseModel.columnLower(i),
                                    baseModel.columnUpper(i),baseModel.objective(i),
                                    baseModel.columnName(i),baseModel.isInteger(i));
                else
                    model.addColumn(n,row,element);
            }
            if (doColumn) {
                columnDone[jColumn]=1;
            }
            delete [] row;
            delete [] element;
        } else {
            // addElement
            // Which way round ?
            if (CoinDrand48()<0.5) {
                // rim first
                if (doRow) {
                    for (i=lastRow[jRow]; i<lastRow[jRow+1]; i++) {
                        model.setRowLower(i,baseModel.getRowLower(i));
                        model.setRowUpper(i,baseModel.getRowUpper(i));
                        model.setRowName(i,baseModel.getRowName(i));
                    }
                    rowDone[jRow]=1;
                }
                if (doColumn) {
                    for (i=lastColumn[jColumn]; i<lastColumn[jColumn+1]; i++) {
                        model.setColumnLower(i,baseModel.getColumnLower(i));
                        model.setColumnUpper(i,baseModel.getColumnUpper(i));
                        model.setColumnName(i,baseModel.getColumnName(i));
                        model.setColumnObjective(i,baseModel.getColumnObjective(i));
                        model.setColumnIsInteger(i,baseModel.getColumnIsInteger(i));
                    }
                    columnDone[jColumn]=1;
                }
                if (CoinDrand48()<0.3) {
                    // by row
                    for (i=lastRow[jRow]; i<lastRow[jRow+1]; i++) {
                        CoinModelLink triple=baseModel.firstInRow(i);
                        while (triple.column()>=0) {
                            int iColumn = triple.column();
                            if (iColumn>=lastColumn[jColumn]&&iColumn<lastColumn[jColumn+1])
                                model(i,triple.column(),triple.value());
                            triple=baseModel.next(triple);
                        }
                    }
                } else if (CoinDrand48()<0.6) {
                    // by column
                    for (i=lastColumn[jColumn]; i<lastColumn[jColumn+1]; i++) {
                        CoinModelLink triple=baseModel.firstInColumn(i);
                        while (triple.row()>=0) {
                            int iRow = triple.row();
                            if (iRow>=lastRow[jRow]&&iRow<lastRow[jRow+1])
                                model(triple.row(),i,triple.value());
                            triple=baseModel.next(triple);
                        }
                    }
                } else {
                    // scan through backwards
                    const CoinModelTriple * elements = baseModel.elements();
                    for (i=baseModel.numberElements()-1; i>=0; i--) {
                        int iRow = (int) rowInTriple(elements[i]);
                        int iColumn = elements[i].column;
                        if (iRow>=lastRow[jRow]&&iRow<lastRow[jRow+1]&&
                                iColumn>=lastColumn[jColumn]&&iColumn<lastColumn[jColumn+1])
                            model(iRow,iColumn,elements[i].value);
                    }
                }
            } else {
                // elements first
                if (CoinDrand48()<0.3) {
                    // by row
                    for (i=lastRow[jRow]; i<lastRow[jRow+1]; i++) {
                        CoinModelLink triple=baseModel.firstInRow(i);
                        while (triple.column()>=0) {
                            int iColumn = triple.column();
                            if (iColumn>=lastColumn[jColumn]&&iColumn<lastColumn[jColumn+1])
                                model(i,triple.column(),triple.value());
                            triple=baseModel.next(triple);
                        }
                    }
                } else if (CoinDrand48()<0.6) {
                    // by column
                    for (i=lastColumn[jColumn]; i<lastColumn[jColumn+1]; i++) {
                        CoinModelLink triple=baseModel.firstInColumn(i);
                        while (triple.row()>=0) {
                            int iRow = triple.row();
                            if (iRow>=lastRow[jRow]&&iRow<lastRow[jRow+1])
                                model(triple.row(),i,triple.value());
                            triple=baseModel.next(triple);
                        }
                    }
                } else {
                    // scan through backwards
                    const CoinModelTriple * elements = baseModel.elements();
                    for (i=baseModel.numberElements()-1; i>=0; i--) {
                        int iRow = (int) rowInTriple(elements[i]);
                        int iColumn = elements[i].column;
                        if (iRow>=lastRow[jRow]&&iRow<lastRow[jRow+1]&&
                                iColumn>=lastColumn[jColumn]&&iColumn<lastColumn[jColumn+1])
                            model(iRow,iColumn,elements[i].value);
                    }
                }
                if (doRow) {
                    for (i=lastRow[jRow]; i<lastRow[jRow+1]; i++) {
                        model.setRowLower(i,baseModel.getRowLower(i));
                        model.setRowUpper(i,baseModel.getRowUpper(i));
                        model.setRowName(i,baseModel.getRowName(i));
                    }
                    rowDone[jRow]=1;
                }
                if (doColumn) {
                    for (i=lastColumn[jColumn]; i<lastColumn[jColumn+1]; i++) {
                        model.setColumnLower(i,baseModel.getColumnLower(i));
                        model.setColumnUpper(i,baseModel.getColumnUpper(i));
                        model.setColumnName(i,baseModel.getColumnName(i));
                        model.setColumnObjective(i,baseModel.getColumnObjective(i));
                        model.setColumnIsInteger(i,baseModel.getColumnIsInteger(i));
                    }
                    columnDone[jColumn]=1;
                }
            }
        }
        // Mess up be deleting some elements
        if (CoinDrand48()<0.3&&iPass>10) {
            double random2=CoinDrand48();
            double randomDelete = 0.2 + 0.5*random2; // fraction to delete
            //model.validateLinks();
            if (random2<0.2) {
                // delete some rows
                for (int j=lastRow[jRow]; j<lastRow[jRow+1]; j++) {
                    //model.validateLinks();
                    if (CoinDrand48()<randomDelete) {
                        // save and delete
                        double rowLower = model.rowLower(j);
                        double rowUpper = model.rowUpper(j);
                        char * rowName = CoinStrdup(model.rowName(j));
                        CoinModelLink triple=model.firstInRow(j);
                        while (triple.column()>=0) {
                            int iColumn = triple.column();
                            assert (j==triple.row());
                            setRowInTriple(dTriple[numberElements],j);
                            dTriple[numberElements].column=iColumn;
                            dTriple[numberElements].value = triple.value();
                            numberElements++;
                            triple=model.next(triple);
                        }
                        model.deleteRow(j);
                        if (rowDone[jRow]) {
                            // put back rim
                            model.setRowLower(j,rowLower);
                            model.setRowUpper(j,rowUpper);
                            model.setRowName(j,rowName);
                        }
                        free(rowName);
                    }
                }
            } else if (random2<0.4) {
                // delete some columns
                for (int j=lastColumn[jColumn]; j<lastColumn[jColumn+1]; j++) {
                    //model.validateLinks();
                    if (CoinDrand48()<randomDelete) {
                        // save and delete
                        double columnLower = model.columnLower(j);
                        double columnUpper = model.columnUpper(j);
                        double objective = model.objective(j);
                        bool integer = model.isInteger(j)!=0;
                        char * columnName = CoinStrdup(model.columnName(j));
                        CoinModelLink triple=model.firstInColumn(j);
                        while (triple.column()>=0) {
                            int iRow = triple.row();
                            assert (j==triple.column());
                            dTriple[numberElements].column = j;
                            setRowInTriple(dTriple[numberElements],iRow);
                            dTriple[numberElements].value = triple.value();
                            numberElements++;
                            triple=model.next(triple);
                        }
                        model.deleteColumn(j);
                        if (columnDone[jColumn]) {
                            // put back rim
                            model.setColumnLower(j,columnLower);
                            model.setColumnUpper(j,columnUpper);
                            model.setObjective(j,objective);
                            model.setIsInteger(j,integer);
                            model.setColumnName(j,columnName);
                        }
                        free(columnName);
                    }
                }
            } else {
                // delete some elements
                //model.validateLinks();
                const CoinModelTriple * elements = baseModel.elements();
                for (i=0; i<model.numberElements(); i++) {
                    int iRow = (int) rowInTriple(elements[i]);
                    int iColumn = elements[i].column;
                    if (iRow>=lastRow[jRow]&&iRow<lastRow[jRow+1]&&
                            iColumn>=lastColumn[jColumn]&&iColumn<lastColumn[jColumn+1]) {
                        if (CoinDrand48()<randomDelete) {
                            dTriple[numberElements].column = iColumn;
                            setRowInTriple(dTriple[numberElements],iRow);
                            dTriple[numberElements].value = elements[i].value;
                            int position = model.deleteElement(iRow,iColumn);
                            if (position>=0)
                                numberElements++;
                        }
                    }
                }
            }
        }
    }
    // Do rim if necessary
    for (int k=0; k<3; k++) {
        if (!rowDone[k]) {
            for (i=lastRow[k]; i<lastRow[k+1]; i++) {
                model.setRowLower(i,baseModel.getRowLower(i));
                model.setRowUpper(i,baseModel.getRowUpper(i));
                model.setRowName(i,baseModel.getRowName(i));
            }
        }
        if (!columnDone[k]) {
            for (i=lastColumn[k]; i<lastColumn[k+1]; i++) {
                model.setColumnLower(i,baseModel.getColumnLower(i));
                model.setColumnUpper(i,baseModel.getColumnUpper(i));
                model.setColumnName(i,baseModel.getColumnName(i));
                model.setColumnObjective(i,baseModel.getColumnObjective(i));
                model.setColumnIsInteger(i,baseModel.getColumnIsInteger(i));
            }
        }
    }
    // Put back any elements
    for (i=0; i<numberElements; i++) {
        model(rowInTriple(dTriple[i]),dTriple[i].column,dTriple[i].value);
    }
    delete [] dTriple;
    timeIt +=  CoinCpuTime()-time1;
    model.setLogLevel(1);
    assert (!model.differentModel(baseModel,false));
}
Exemple #9
0
int main (int argc, const char *argv[])
{
  // Get data
  std::string fileName = "./sudoku_sample.csv";
  if (argc>=2) fileName = argv[1];
  FILE * fp = fopen(fileName.c_str(),"r");
  if (!fp) {
    printf("Unable to open file %s\n",fileName.c_str());
    exit(0);
  }
#define MAX_SIZE 16
  int valueOffset=1;
  double lo[MAX_SIZE*MAX_SIZE],up[MAX_SIZE*MAX_SIZE];
  char line[80];
  int row,column;
  /*************************************** 
     Read .csv file and see if 9 or 16 Su Doku
  ***************************************/
  int size=9;
  for (row=0;row<size;row++) {
    fgets(line,80,fp);
    // Get size of sudoku puzzle (9 or 16)
    if (!row) {
      int get=0;
      size=1;
      while (line[get]>=32) {
        if (line[get]==',')
          size++;
        get++;
      }
      assert (size==9||size==16);
      printf("Solving Su Doku of size %d\n",size);
      if (size==16)
        valueOffset=0;
    }
    int get=0;
    for (column=0;column<size;column++) {
      lo[size*row+column]=valueOffset;
      up[size*row+column]=valueOffset-1+size;
      if (line[get]!=','&&line[get]>=32) {
        // skip blanks
        if (line[get]==' ') {
          get++;
          continue;
        }
        int value = line[get]-'0';
        if (size==9) {
          assert (value>=1&&value<=9);
        } else {
          assert (size==16);
          if (value<0||value>9) {
            if (line[get]=='"') {
              get++;
              value = 10 + line[get]-'A';
              if (value<10||value>15) {
                value = 10 + line[get]-'a';
              }
              get++;
            } else {
              value = 10 + line[get]-'A';
              if (value<10||value>15) {
                value = 10 + line[get]-'a';
              }
          }
          }
          assert (value>=0&&value<=15);
        }
        lo[size*row+column]=value;
        up[size*row+column]=value;
        get++;
      }
      get++;
    }
  }
  int block_size = (int) sqrt ((double) size);
  /*************************************** 
     Now build rules for all different
     3*9 or 3*16 sets of variables
     Number variables by row*size+column
  ***************************************/
  int starts[3*MAX_SIZE+1];
  int which[3*MAX_SIZE*MAX_SIZE];
  int put=0;
  int set=0;
  starts[0]=0;
  // By row
  for (row=0;row<size;row++) {
    for (column=0;column<size;column++) 
      which[put++]=row*size+column;
    starts[set+1]=put;
    set++;
  }
  // By column
  for (column=0;column<size;column++) {
    for (row=0;row<size;row++) 
      which[put++]=row*size+column;
    starts[set+1]=put;
    set++;
  }
  // By box
  for (row=0;row<size;row+=block_size) {
    for (column=0;column<size;column+=block_size) {
      for (int row2=row;row2<row+block_size;row2++) {
        for (int column2=column;column2<column+block_size;column2++) 
          which[put++]=row2*size+column2;
      }
      starts[set+1]=put;
      set++;
    }
  }
  OsiClpSolverInterface solver1;

  /*************************************** 
     Create model
     Set variables to be general integer variables although
     priorities probably mean that it won't matter
  ***************************************/
  CoinModel build;
  // Columns
  char name[4];
  for (row=0;row<size;row++) {
    for (column=0;column<size;column++) {
      if (row<10) {
        if (column<10) 
          sprintf(name,"X%d%d",row,column);
        else
          sprintf(name,"X%d%c",row,'A'+(column-10));
      } else {
        if (column<10) 
          sprintf(name,"X%c%d",'A'+(row-10),column);
        else
          sprintf(name,"X%c%c",'A'+(row-10),'A'+(column-10));
      }
      double value = CoinDrand48()*100.0;
      build.addColumn(0,NULL,NULL,lo[size*row+column],
                      up[size*row+column], value, name,true);
    }
  }
  /*************************************** 
     Now add in extra variables for N way branching
  ***************************************/
  for (row=0;row<size;row++) {
    for (column=0;column<size;column++) {
      int iColumn = size*row+column;
      double value = lo[iColumn];
      if (value<up[iColumn]) {
        for (int i=0;i<size;i++)
          build.addColumn(0,NULL,NULL,0.0,1.0,0.0);
      } else {
        // fixed
        // obviously could do better  if we missed out variables
        int which = ((int) value) - valueOffset;
        for (int i=0;i<size;i++) {
          if (i!=which)
            build.addColumn(0,NULL,NULL,0.0,0.0,0.0);
          else
            build.addColumn(0,NULL,NULL,0.0,1.0,0.0);
        }
      }
    }
  }
  
  /*************************************** 
     Now rows
  ***************************************/
  double values[]={1.0,1.0,1.0,1.0,
                   1.0,1.0,1.0,1.0,
                   1.0,1.0,1.0,1.0,
                   1.0,1.0,1.0,1.0};
  int indices[MAX_SIZE+1];
  double rhs = size==9 ? 45.0 : 120.0;
  for (row=0;row<3*size;row++) {
    int iStart = starts[row];
    for (column=0;column<size;column++) 
      indices[column]=which[column+iStart];
    build.addRow(size,indices,values,rhs,rhs);
  }
  double values2[MAX_SIZE+1];
  values2[0]=-1.0;
  for (row=0;row<size;row++) 
    values2[row+1]=row+valueOffset;
  // Now add rows for extra variables
  for (row=0;row<size;row++) {
    for (column=0;column<size;column++) {
      int iColumn = row*size+column;
      int base = size*size + iColumn*size;
      indices[0]=iColumn;
      for (int i=0;i<size;i++)
        indices[i+1]=base+i;
      build.addRow(size+1,indices,values2,0.0,0.0);
    }
  }
  solver1.loadFromCoinModel(build);
  build.writeMps("xx.mps");
  
  double time1 = CoinCpuTime();
  solver1.initialSolve();
  CbcModel model(solver1);
  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
  model.solver()->setHintParam(OsiDoScale,false,OsiHintTry);
  /*************************************** 
    Add in All different cut generator and All different branching
    So we will have integers then cut branching then N way branching
    in reverse priority order
  ***************************************/
  
  // Cut generator
  CglAllDifferent allDifferent(3*size,starts,which);
  model.addCutGenerator(&allDifferent,-99,"allDifferent");
  model.cutGenerator(0)->setWhatDepth(5);
  CbcObject ** objects = new CbcObject * [4*size*size];
  int nObj=0;
  for (row=0;row<3*size;row++) {
    int iStart = starts[row];
    objects[row]= new CbcBranchAllDifferent(&model,size,which+iStart);
    objects[row]->setPriority(2000+nObj); // do after rest satisfied
    nObj++;
  }
  /*************************************** 
     Add in N way branching and while we are at it add in cuts
  ***************************************/
  CglStored stored;
  for (row=0;row<size;row++) {
    for (column=0;column<size;column++) {
      int iColumn = row*size+column;
      int base = size*size + iColumn*size;
      int i;
      for ( i=0;i<size;i++)
        indices[i]=base+i;
      CbcNWay * obj = new CbcNWay(&model,size,indices,nObj);
      int seq[200];
      int newUpper[200];
      memset(newUpper,0,sizeof(newUpper));
      for (i=0;i<size;i++) {
        int state=9999;
        int one=1;
        int nFix=1;
        // Fix real variable
        seq[0]=iColumn;
        newUpper[0]=valueOffset+i;
        int kColumn = base+i;
        int j;
        // same row
        for (j=0;j<size;j++) {
          int jColumn = row*size+j;
          int jjColumn = size*size+jColumn*size+i;
          if (jjColumn!=kColumn) {
            seq[nFix++]=jjColumn; // must be zero
          }
        }
        // same column
        for (j=0;j<size;j++) {
          int jColumn = j*size+column;
          int jjColumn = size*size+jColumn*size+i;
          if (jjColumn!=kColumn) {
            seq[nFix++]=jjColumn; // must be zero
          }
        }
        // same block
        int kRow = row/block_size;
        kRow *= block_size;
        int kCol = column/block_size;
        kCol *= block_size;
        for (j=kRow;j<kRow+block_size;j++) {
          for (int jc=kCol;jc<kCol+block_size;jc++) {
            int jColumn = j*size+jc;
            int jjColumn = size*size+jColumn*size+i;
            if (jjColumn!=kColumn) {
              seq[nFix++]=jjColumn; // must be zero
            }
          }
        }
        // seem to need following?
        const int * upperAddress = newUpper;
        const int * seqAddress = seq;
        CbcFixVariable fix(1,&state,&one,&upperAddress,&seqAddress,&nFix,&upperAddress,&seqAddress);
        obj->setConsequence(indices[i],fix);
        // Now do as cuts
        for (int kk=1;kk<nFix;kk++) {
          int jColumn = seq[kk];
          int cutInd[2];
          cutInd[0]=kColumn;
          if (jColumn>kColumn) {
            cutInd[1]=jColumn;
            stored.addCut(-COIN_DBL_MAX,1.0,2,cutInd,values);
          }
        }
      }
      objects[nObj]= obj;
      objects[nObj]->setPriority(nObj);
      nObj++;
    }
  }
  model.addObjects(nObj,objects);
  for (row=0;row<nObj;row++) 
    delete objects[row];
  delete [] objects;
  model.messageHandler()->setLogLevel(1);
  model.addCutGenerator(&stored,1,"stored");
  // Say we want timings
  int numberGenerators = model.numberCutGenerators();
  int iGenerator;
  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
    generator->setTiming(true);
  }
  // Set this to get all solutions (all ones in newspapers should only have one)
  //model.setCutoffIncrement(-1.0e6);
  /*************************************** 
     Do branch and bound
  ***************************************/
  // Do complete search
  model.branchAndBound();
  std::cout<<"took "<<CoinCpuTime()-time1<<" seconds, "
	   <<model.getNodeCount()<<" nodes with objective "
	   <<model.getObjValue()
	   <<(!model.status() ? " Finished" : " Not finished")
	   <<std::endl;


  /*************************************** 
     Print solution and check it is feasible
     We could modify output so could be imported by spreadsheet
  ***************************************/
  if (model.getMinimizationObjValue()<1.0e50) {
    
    const double * solution = model.bestSolution();
    int put=0;
    for (row=0;row<size;row++) {
      for (column=0;column<size;column++) {
        int value = (int) floor(solution[row*size+column]+0.5);
        assert (value>=lo[put]&&value<=up[put]);
        // save for later test
        lo[put++]=value;
        printf("%d ",value);
      }
      printf("\n");
    }
    // check valid
    bool valid=true;
    // By row
    for (row=0;row<size;row++) {
      put=0;
      for (column=0;column<size;column++) 
        which[put++]=row*size+column;
      assert (put==size);
      int i;
      for (i=0;i<put;i++) 
        which[i]=(int) lo[which[i]];
      std::sort(which,which+put);
      int last = valueOffset-1;
      for (i=0;i<put;i++) {
        int value=which[i];
        if (value!=last+1)
          valid=false;
        last=value;
      }
    }
    // By column
    for (column=0;column<size;column++) {
      put=0;
      for (row=0;row<size;row++) 
        which[put++]=row*size+column;
      assert (put==size);
      int i;
      for (i=0;i<put;i++) 
        which[i]=(int) lo[which[i]];
      std::sort(which,which+put);
      int last = valueOffset-1;
      for (i=0;i<put;i++) {
        int value=which[i];
        if (value!=last+1)
          valid=false;
        last=value;
      }
    }
    // By box
    for (row=0;row<size;row+=block_size) {
      for (column=0;column<size;column+=block_size) {
        put=0;
        for (int row2=row;row2<row+block_size;row2++) {
          for (int column2=column;column2<column+block_size;column2++) 
            which[put++]=row2*size+column2;
        }
        assert (put==size);
        int i;
        for (i=0;i<put;i++) 
          which[i]=(int) lo[which[i]];
        std::sort(which,which+put);
        int last = valueOffset-1;
        for (i=0;i<put;i++) {
          int value=which[i];
          if (value!=last+1)
          valid=false;
          last=value;
        }
      }
    }
    if (valid) {
      printf("solution is valid\n");
    } else {
      printf("solution is not valid\n");
      abort();
    }
  }
  return 0;
}    
Exemple #10
0
// See if rounding will give solution
// Sets value of solution
// Assumes rhs for original matrix still okay
// At present only works with integers 
// Fix values if asked for
// Returns 1 if solution, 0 if not
int
AbcRounding::solution(double & solutionValue,
		      double * betterSolution)
{
    // Get a copy of original matrix (and by row for rounding);
    matrix_ = *(model_->solver()->getMatrixByCol());
    matrixByRow_ = *(model_->solver()->getMatrixByRow());
    seed_=1;

    OsiSolverInterface * solver = model_->solver();
    const double * lower = solver->getColLower();
    const double * upper = solver->getColUpper();
    const double * rowLower = solver->getRowLower();
    const double * rowUpper = solver->getRowUpper();
    const double * solution = solver->getColSolution();
    const double * objective = solver->getObjCoefficients();
    double integerTolerance = 1.0e-5;
    //model_->getDblParam(AbcModel::AbcIntegerTolerance);
    double primalTolerance;
    solver->getDblParam(OsiPrimalTolerance, primalTolerance);

    int numberRows = matrix_.getNumRows();

    int numberIntegers = model_->numberIntegers();
    const int * integerVariable = model_->integerVariable();
    int i;
    double direction = solver->getObjSense();
    double newSolutionValue = direction * solver->getObjValue();
    int returnCode = 0;

    // Column copy
    const double * element = matrix_.getElements();
    const int * row = matrix_.getIndices();
    const int * columnStart = matrix_.getVectorStarts();
    const int * columnLength = matrix_.getVectorLengths();
    // Row copy
    const double * elementByRow = matrixByRow_.getElements();
    const int * column = matrixByRow_.getIndices();
    const int * rowStart = matrixByRow_.getVectorStarts();
    const int * rowLength = matrixByRow_.getVectorLengths();

    // Get solution array for heuristic solution
    int numberColumns = solver->getNumCols();
    double * newSolution = new double [numberColumns];
    memcpy(newSolution, solution, numberColumns * sizeof(double));

    double * rowActivity = new double[numberRows];
    memset(rowActivity, 0, numberRows*sizeof(double));
    for (i = 0; i < numberColumns; i++) {
	int j;
	double value = newSolution[i];
	if (value) {
	    for (j = columnStart[i];
		 j < columnStart[i] + columnLength[i]; j++) {
		int iRow = row[j];
		rowActivity[iRow] += value*element[j];
	    }
	}
    }
    // check was feasible - if not adjust (cleaning may move)
    for (i = 0; i < numberRows; i++) {
	if(rowActivity[i] < rowLower[i]) {
	    //assert (rowActivity[i]>rowLower[i]-1000.0*primalTolerance);
	    rowActivity[i] = rowLower[i];
	} else if(rowActivity[i] > rowUpper[i]) {
	    //assert (rowActivity[i]<rowUpper[i]+1000.0*primalTolerance);
	    rowActivity[i] = rowUpper[i];
	}
    }
    for (i = 0; i < numberIntegers; i++) {
	int iColumn = integerVariable[i];
	double value = newSolution[iColumn];
	if (fabs(floor(value + 0.5) - value) > integerTolerance) {
	    double below = floor(value);
	    double newValue = newSolution[iColumn];
	    double cost = direction * objective[iColumn];
	    double move;
	    if (cost > 0.0) {
		// try up
		move = 1.0 - (value - below);
	    } else if (cost < 0.0) {
		// try down
		move = below - value;
	    } else {
		// won't be able to move unless we can grab another variable
		// just for now go down
		move = below-value;
	    }
	    newValue += move;
	    newSolution[iColumn] = newValue;
	    newSolutionValue += move * cost;
	    int j;
	    for (j = columnStart[iColumn];
		 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
		int iRow = row[j];
		rowActivity[iRow] += move * element[j];
	    }
	}
    }

    double penalty = 0.0;
  
    // see if feasible
    for (i = 0; i < numberRows; i++) {
	double value = rowActivity[i];
	double thisInfeasibility = 0.0;
	if (value < rowLower[i] - primalTolerance)
	    thisInfeasibility = value - rowLower[i];
	else if (value > rowUpper[i] + primalTolerance)
	    thisInfeasibility = value - rowUpper[i];
	if (thisInfeasibility) {
	    // See if there are any slacks I can use to fix up
	    // maybe put in coding for multiple slacks?
	    double bestCost = 1.0e50;
	    int k;
	    int iBest = -1;
	    double addCost = 0.0;
	    double newValue = 0.0;
	    double changeRowActivity = 0.0;
	    double absInfeasibility = fabs(thisInfeasibility);
	    for (k = rowStart[i]; k < rowStart[i] + rowLength[i]; k++) {
		int iColumn = column[k];
		if (columnLength[iColumn] == 1) {
		    double currentValue = newSolution[iColumn];
		    double elementValue = elementByRow[k];
		    double lowerValue = lower[iColumn];
		    double upperValue = upper[iColumn];
		    double gap = rowUpper[i] - rowLower[i];
		    double absElement = fabs(elementValue);
		    if (thisInfeasibility * elementValue > 0.0) {
			// we want to reduce
			if ((currentValue - lowerValue) * absElement >= 
			    absInfeasibility) {
			    
			    // possible - check if integer
			    double distance = absInfeasibility / absElement;
			    double thisCost = 
				-direction * objective[iColumn] * distance;
			    if (solver->isInteger(iColumn)) {
				distance = ceil(distance - primalTolerance);
				assert (currentValue - distance >= 
					lowerValue - primalTolerance);
				if (absInfeasibility - distance * absElement 
				    < -gap - primalTolerance)
				    thisCost = 1.0e100; // no good
				else
				    thisCost = 
					-direction*objective[iColumn]*distance;
			    }
			    if (thisCost < bestCost) {
				bestCost = thisCost;
				iBest = iColumn;
				addCost = thisCost;
				newValue = currentValue - distance;
				changeRowActivity = -distance * elementValue;
			    }
			}
		    } else {
			// we want to increase
			if ((upperValue - currentValue) * absElement >= 
			    absInfeasibility) {
			    // possible - check if integer
			    double distance = absInfeasibility / absElement;
			    double thisCost = 
				direction * objective[iColumn] * distance;
			    if (solver->isInteger(iColumn)) {
				distance = ceil(distance - 1.0e-7);
				assert (currentValue - distance <= 
					upperValue + primalTolerance);
				if (absInfeasibility - distance * absElement 
				    < -gap - primalTolerance)
				    thisCost = 1.0e100; // no good
				else
				    thisCost = 
					direction*objective[iColumn]*distance;
			    }
			    if (thisCost < bestCost) {
				bestCost = thisCost;
				iBest = iColumn;
				addCost = thisCost;
				newValue = currentValue + distance;
				changeRowActivity = distance * elementValue;
			    }
			}
		    }
		}
	    }
	    if (iBest >= 0) {
		/*printf("Infeasibility of %g on row %d cost %g\n",
		  thisInfeasibility,i,addCost);*/
		newSolution[iBest] = newValue;
		thisInfeasibility = 0.0;
		newSolutionValue += addCost;
		rowActivity[i] += changeRowActivity;
	    }
	    penalty += fabs(thisInfeasibility);
	}
    }

    // Could also set SOS (using random) and repeat
    if (!penalty) {
	// See if we can do better
	//seed_++;
	//CoinSeedRandom(seed_);
	// Random number between 0 and 1.
	double randomNumber = CoinDrand48();
	int iPass;
	int start[2];
	int end[2];
	int iRandom = (int) (randomNumber * ((double) numberIntegers));
	start[0] = iRandom;
	end[0] = numberIntegers;
	start[1] = 0;
	end[1] = iRandom;
	for (iPass = 0; iPass < 2; iPass++) {
	    int i;
	    for (i = start[iPass]; i < end[iPass]; i++) {
		int iColumn = integerVariable[i];
		double value = newSolution[iColumn];
		assert(fabs(floor(value + 0.5) - value) < integerTolerance);
		double cost = direction * objective[iColumn];
		double move = 0.0;
		if (cost > 0.0)
		    move = -1.0;
		else if (cost < 0.0)
		    move = 1.0;
		while (move) {
		    bool good = true;
		    double newValue = newSolution[iColumn] + move;
		    if (newValue < lower[iColumn] - primalTolerance||
			newValue > upper[iColumn] + primalTolerance) {
			move = 0.0;
		    } else {
			// see if we can move
			int j;
			for (j = columnStart[iColumn];
			     j < columnStart[iColumn] + columnLength[iColumn];
			     j++) {
			    int iRow = row[j];
			    double newActivity = 
				rowActivity[iRow] + move*element[j];
			    if (newActivity < rowLower[iRow] - primalTolerance
				||
				newActivity > rowUpper[iRow]+primalTolerance) {
				good = false;
				break;
			    }
			}
			if (good) {
			    newSolution[iColumn] = newValue;
			    newSolutionValue += move * cost;
			    int j;
			    for (j = columnStart[iColumn];
				 j < columnStart[iColumn] + 
				     columnLength[iColumn]; j++) {
				int iRow = row[j];
				rowActivity[iRow] += move*element[j];
			    }
			} else {
			    move=0.0;
			}
		    }
		}
	    }
	}
	if (newSolutionValue < solutionValue) {
	    // paranoid check
	    memset(rowActivity, 0, numberRows * sizeof(double));
	    for (i = 0; i < numberColumns; i++) {
		int j;
		double value = newSolution[i];
		if (value) {
		    for (j = columnStart[i];
			 j < columnStart[i] + columnLength[i]; j++) {
			int iRow = row[j];
			rowActivity[iRow] += value * element[j];
		    }
		}
	    }
	    // check was approximately feasible
	    bool feasible = true;
	    for (i = 0; i < numberRows; i++) {
		if(rowActivity[i] < rowLower[i]) {
		    if (rowActivity[i] < rowLower[i] - 1000.0*primalTolerance)
			feasible = false;
		} else if(rowActivity[i] > rowUpper[i]) {
		    if (rowActivity[i] > rowUpper[i] + 1000.0*primalTolerance)
			feasible = false;
		}
	    }
	    if (feasible) {
		// new solution
		memcpy(betterSolution, newSolution, 
		       numberColumns * sizeof(double));
		solutionValue = newSolutionValue;
		//printf("** Solution of %g found by rounding\n",newSolutionValue);
		returnCode=1;
	    } else {
		// Can easily happen
		//printf("Debug AbcRounding giving bad solution\n");
	    }
	}
    }
    delete [] newSolution;
    delete [] rowActivity;
    return returnCode;
}
Exemple #11
0
void CouenneCutGenerator::generateCuts (const OsiSolverInterface &si,
					OsiCuts &cs, 
					const CglTreeInfo info)
#if CGL_VERSION_MAJOR == 0 && CGL_VERSION_MINOR <= 57
  const
#endif
  {

  // check if out of time or if an infeasibility cut (iis of type 0)
  // was added as a result of, e.g., pruning on BT. If so, no need to
  // run this.

  if (isWiped (cs) || 
     (CoinCpuTime () > problem_ -> getMaxCpuTime ()))
    return;

#ifdef FM_TRACE_OPTSOL
  double currCutOff = problem_->getCutOff();
  double bestVal = 1e50;
  CouenneRecordBestSol *rs = problem_->getRecordBestSol();
  if(rs->getHasSol()) {
    bestVal = rs->getVal(); 
  }
  if(currCutOff > bestVal) {
    //problem_ -> setCutOff (bestVal - 1e-6); // FIXME: don't add numerical constants
    problem_ -> setCutOff (bestVal);

    int indObj = problem_->Obj(0)->Body()->Index();

    if (indObj >= 0) {
      OsiColCut *objCut = new OsiColCut;
      objCut->setUbs(1, &indObj, &bestVal);
      cs.insert(objCut);
      delete objCut;
    }
  }
#endif

#ifdef FM_PRINT_INFO
  if((BabPtr_ != NULL) && (info.level >= 0) && (info.pass == 0) && 
     (BabPtr_->model().getNodeCount() > lastPrintLine)) {
    printLineInfo();
    lastPrintLine += 1;
  }
#endif

  const int infeasible = 1;

  int nInitCuts = cs.sizeRowCuts ();

  CouNumber
    *&realOpt = problem_ -> bestSol (),
    *saveOptimum = realOpt;

  if (!firstcall_ && realOpt) { 

    // have a debug optimal solution. Check if current bounds
    // contain it, otherwise pretend it does not exist

    CouNumber *opt = realOpt;

    const CouNumber 
      *sol = si.getColSolution (),
      *lb  = si.getColLower (),
      *ub  = si.getColUpper ();

    int objind = problem_ -> Obj (0) -> Body () -> Index ();

    for (int j=0, i=problem_ -> nVars (); i--; j++, opt++, lb++, ub++)
      if ((j != objind) && 
	  ((*opt < *lb - COUENNE_EPS * (1 + CoinMin (fabs (*opt), fabs (*lb)))) || 
	   (*opt > *ub + COUENNE_EPS * (1 + CoinMin (fabs (*opt), fabs (*ub)))))) {
	
	jnlst_ -> Printf (J_VECTOR, J_CONVEXIFYING, 
			  "out of bounds, ignore x%d = %g [%g,%g] opt = %g\n", 
			  problem_ -> nVars () - i - 1, *sol, *lb, *ub, *opt);

	// optimal point is not in current bounding box,
	// pretend realOpt is NULL until we return from this procedure
	realOpt = NULL;
	break;
      }
  }

  /*static int count = 0;
  char fname [20];
  sprintf (fname, "relax_%d", count++);
  si.writeLp (fname);
  printf ("writing %s\n", fname);*/

  jnlst_ -> Printf (J_DETAILED, J_CONVEXIFYING,
		    "generateCuts: level = %d, pass = %d, intree = %d\n",
		    info.level, info.pass, info.inTree);

  Bonmin::BabInfo * babInfo = dynamic_cast <Bonmin::BabInfo *> (si.getAuxiliaryInfo ());

  if (babInfo)
    babInfo -> setFeasibleNode ();

  double now   = CoinCpuTime ();
  int    ncols = problem_ -> nVars ();

  // This vector contains variables whose bounds have changed due to
  // branching, reduced cost fixing, or bound tightening below. To be
  // used with malloc/realloc/free

  t_chg_bounds *chg_bds = new t_chg_bounds [ncols];

  /*for (int i=0; i < ncols; i++) 
    if (problem_ -> Var (i) -> Multiplicity () <= 0) {
      chg_bds [i].setLower (t_chg_bounds::UNCHANGED);
      chg_bds [i].setUpper (t_chg_bounds::UNCHANGED);
      }*/

  problem_ -> installCutOff (); // install upper bound

  if (firstcall_) {

    // First convexification //////////////////////////////////////

    // OsiSolverInterface is empty yet, no information can be obtained
    // on variables or bounds -- and none is needed since our
    // constructor populated *problem_ with variables and bounds. We
    // only need to update the auxiliary variables and bounds with
    // their current value.

    for (int i=0; i < ncols; i++) 
      if (problem_ -> Var (i) -> Multiplicity () > 0) {
	chg_bds [i].setLower (t_chg_bounds::CHANGED);
	chg_bds [i].setUpper (t_chg_bounds::CHANGED);
      }

    // start with FBBT, should take advantage of cutoff found by NLP
    // run AFTER initial FBBT...
    if (problem_ -> doFBBT () &&
	(! (problem_ -> boundTightening (chg_bds, babInfo))))
          jnlst_ -> Printf (J_STRONGWARNING, J_CONVEXIFYING,
            "Couenne: WARNING, first convexification is infeasible\n");

    // For each auxiliary variable replacing the original (nonlinear)
    // constraints, check if corresponding bounds are violated, and
    // add cut to cs

    int nnlc = problem_ -> nCons ();

    for (int i=0; i<nnlc; i++) {

      if (CoinCpuTime () > problem_ -> getMaxCpuTime ())
	break;

      // for each constraint
      CouenneConstraint *con = problem_ -> Con (i);

      // (which has an aux as its body)
      int objindex = con -> Body () -> Index ();

      if ((objindex >= 0) && 
	  ((con -> Body () -> Type () == AUX) ||
	   (con -> Body () -> Type () == VAR))) {

	// get the auxiliary that is at the lhs
	exprVar *conaux = problem_ -> Var (objindex);

	if (conaux &&
	    (conaux -> Type () == AUX) &&
	    (conaux -> Image ()) && 
	    (conaux -> Image () -> Linearity () <= LINEAR)) {

	  // reduce density of problem by adding w >= l rather than
	  // ax + b >= l for any linear auxiliary defined as w := ax+b

	  double 
	    lb = (*(con -> Lb ())) (), 
	    ub = (*(con -> Ub ())) ();

	  OsiColCut newBound;
	  if (lb > -COUENNE_INFINITY) newBound.setLbs (1, &objindex, &lb);
	  if (ub <  COUENNE_INFINITY) newBound.setUbs (1, &objindex, &ub);

	  cs.insert (newBound);

	  // the auxiliary w of constraint w <= b is associated with a
	  // linear expression w = ax: add constraint ax <= b
	  /*conaux -> Image () -> generateCuts (conaux, si, cs, this, chg_bds, 
					      conaux -> Index (), 
					      (*(con -> Lb ())) (), 
					      (*(con -> Ub ())) ());*/

	  // take it from the list of the variables to be linearized
	  // 
	  // DO NOT decrease multiplicity. Even if it is a linear
	  // term, its bounds can still be used in implied bounds
	  //
	  // Are we sure? That will happen only if its multiplicity is
	  // nonzero, for otherwise this aux is only used here, and is
	  // useless elsewhere
	  //
	  //conaux -> decreaseMult (); // !!!
	}

	// also, add constraint w <= b

	// not now, do it later

// 	// if there exists violation, add constraint
// 	CouNumber l = con -> Lb () -> Value (),	
// 	          u = con -> Ub () -> Value ();

// 	// tighten bounds in Couenne's problem representation
// 	problem_ -> Lb (index) = CoinMax (l, problem_ -> Lb (index));
// 	problem_ -> Ub (index) = CoinMin (u, problem_ -> Ub (index));

      } else { // body is more than just a variable, but it should be
	       // linear. If so, generate equivalent linear cut

	assert (false);	// TODO
      }
    }

    if (jnlst_ -> ProduceOutput (J_ITERSUMMARY, J_CONVEXIFYING)) {
      if (cs.sizeRowCuts ()) {
	jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne: %d constraint row cuts\n",
			  cs.sizeRowCuts ());
	for (int i=0; i<cs.sizeRowCuts (); i++) 
	  cs.rowCutPtr (i) -> print ();
      }
      if (cs.sizeColCuts ()) {
	jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne: %d constraint col cuts\n",
			  cs.sizeColCuts ());
	for (int i=0; i<cs.sizeColCuts (); i++) 
	  cs.colCutPtr (i) -> print ();
      }
    }
  } else {

    // use new optimum as lower bound for variable associated w/objective
    int indobj = problem_ -> Obj (0) -> Body () -> Index ();

    // transmit solution from OsiSolverInterface to problem
    problem_ -> domain () -> push (&si, &cs);

    if (indobj >= 0) {

      // Use current value of objvalue's x as a lower bound for bound
      // tightening
      double lp_bound = problem_ -> domain () -> x (indobj);

      //if (problem_ -> Obj (0) -> Sense () == MINIMIZE) 
      {if (lp_bound > problem_ -> Lb (indobj)) problem_ -> Lb (indobj) = lp_bound;}
	   //else {if (lp_bound < problem_ -> Ub (indobj)) problem_ -> Ub (indobj) = lp_bound;}
    }

    updateBranchInfo (si, problem_, chg_bds, info); // info.depth >= 0 || info.pass >= 0
  }

  // restore constraint bounds before tightening and cut generation
  for (int i = problem_ -> nCons (); i--;) {

    // for each constraint
    CouenneConstraint *con = problem_ -> Con (i);

    // (which has an aux as its body)
    int objindex = con -> Body () -> Index ();

    if ((objindex >= 0) && 
	((con -> Body () -> Type () == AUX) ||
	 (con -> Body () -> Type () == VAR))) {

      // if there exists violation, add constraint
      CouNumber 
	l = con -> Lb () -> Value (),	
	u = con -> Ub () -> Value ();

      // tighten bounds in Couenne's problem representation
      problem_ -> Lb (objindex) = CoinMax (l, problem_ -> Lb (objindex));
      problem_ -> Ub (objindex) = CoinMin (u, problem_ -> Ub (objindex));
    }
  }

  problem_ -> installCutOff (); // install upper bound

  fictitiousBound (cs, problem_, false); // install finite lower bound, if currently -inf

  int *changed = NULL, nchanged;

  // Bound tightening ///////////////////////////////////////////

  // do bound tightening only at first pass of cutting plane in a node
  // of BB tree (info.pass == 0) or if first call (creation of RLT,
  // info.pass == -1)

  try {

    // Before bound tightening, compute symmetry group. After bound
    // tightening is done, we can apply further tightening using orbit
    // information.

#ifdef COIN_HAS_NTY
    //    ChangeBounds (psi -> getColLower (),  
    //		  psi -> getColUpper (), 
    //		  psi -> getNumCols ());
    if (problem_ -> orbitalBranching ())
      problem_ -> Compute_Symmetry ();
#endif

    // Bound tightening ////////////////////////////////////

    /*printf ("== BT ================\n");
      for (int i = 0; i < problem_ -> nVars (); i++)
      if (problem_ -> Var (i) -> Multiplicity () > 0)
      printf ("%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
      problem_ -> X  (i), problem_ -> Lb (i), problem_ -> Ub (i));
      printf("=============================\n");*/

    // Reduced Cost BT -- to be done first to use rcost correctly
    if (!firstcall_  &&                         // have a linearization already
	problem_ -> doRCBT () &&                // authorized to do reduced cost tightening
	problem_ -> redCostBT (&si, chg_bds) && // some variables were tightened with reduced cost
	!(problem_ -> btCore (chg_bds)))        // in this case, do another round of FBBT
      throw infeasible;

    // FBBT
    if (problem_ -> doFBBT () && 
	//(info.pass <= 0) && // do it in subsequent rounds too
	(! (problem_ -> boundTightening (chg_bds, babInfo))))
      throw infeasible;

    // OBBT
    if (!firstcall_ && // no obbt if first call (there is no LP to work with)
	problem_ -> obbt (this, si, cs, info, babInfo, chg_bds) < 0)
      throw infeasible;

    // Bound tightening done /////////////////////////////

    if ((problem_ -> doFBBT () ||
	 problem_ -> doOBBT () ||
	 problem_ -> doABT  ()) &&
	(jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING))) {

      jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== after bt =============\n");
      for (int i = 0; i < problem_ -> nVars (); i++)
	if (problem_ -> Var (i) -> Multiplicity () > 0)
	  jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
			 problem_ -> X  (i), problem_ -> Lb (i), problem_ -> Ub (i));
      jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
    }

    // Use orbit info to tighten bounds

#ifdef COIN_HAS_NTY

    // TODO: when independent bound tightener, can get original bounds
    // through si.getCol{Low,Upp}er()

    if (problem_ -> orbitalBranching () && !firstcall_) {

      CouNumber 
	*lb = problem_ -> Lb (),
	*ub = problem_ -> Ub ();

      std::vector<std::vector<int> > *new_orbits = problem_ -> getNtyInfo () -> getOrbits();

      for (int i=0, ii = problem_ -> getNtyInfo () -> getNumOrbits (); ii--; i++){

	CouNumber
	  ll = -COUENNE_INFINITY,
	  uu =  COUENNE_INFINITY; 
	
	std::vector <int> orbit = (*new_orbits)[i];

	if (orbit.size () <= 1)
	  continue; // not much to do when only one variable in this orbit

	if (jnlst_ -> ProduceOutput (J_VECTOR, J_BOUNDTIGHTENING)) {
	  printf ("orbit bounds: "); fflush (stdout);
	  for(int j = 0; j < orbit.size (); j++) {
	    printf ("x_%d [%g,%g] ", orbit[j], lb [orbit [j]], ub [orbit [j]]);
	    fflush (stdout);
	  }
	  printf ("\n");
	}

	for (int j = 0; j < orbit.size (); j++) {
 
	  int indOrb = orbit [j];

	  if (indOrb < problem_ -> nVars ()) {

	    if (lb [indOrb] > ll) ll = lb [indOrb];
	    if (ub [indOrb] < uu) uu = ub [indOrb];
	  }
	}

	jnlst_ -> Printf (J_VECTOR, J_BOUNDTIGHTENING, 
			  " --> new common lower bounds: [%g,--]\n", ll);

	for(int j = 0; j < orbit.size (); j++) {

	  int indOrb = orbit [j];

	  if (indOrb < problem_ -> nVars ()){

	    lb [indOrb] = ll;
	    ub [indOrb] = uu;
	  }
	}
      }

      delete new_orbits;
    }

#endif

    // Generate convexification cuts //////////////////////////////

    sparse2dense (ncols, chg_bds, changed, nchanged);

    double *nlpSol = NULL;

    //--------------------------------------------

    if (true) {

      if (babInfo) 
	nlpSol = const_cast <double *> (babInfo -> nlpSolution ());

      // Aggressive Bound Tightening ////////////////////////////////

      int logAbtLev = problem_ -> logAbtLev ();

      if (problem_ -> doABT () &&             // flag is checked, AND
	  ((logAbtLev != 0) ||                // (parameter is nonzero OR
	   (info.level == 0)) &&              //  we are at root node), AND
	  (info.pass == 0) &&                 // at first round of cuts, AND 
	  ((logAbtLev < 0) ||                 // (logAbtLev = -1, OR
	   (info.level <= logAbtLev) ||       //  depth is lower than COU_OBBT_CUTOFF_LEVEL, OR
	   (CoinDrand48 () <                  //  probability inversely proportional to the level)
	    pow (2., (double) logAbtLev - (info.level + 1))))) {

	jnlst_ -> Printf(J_VECTOR, J_BOUNDTIGHTENING,"  performing ABT\n");
	if (! (problem_ -> aggressiveBT (nlp_, chg_bds, info, babInfo)))
	  throw infeasible;

	sparse2dense (ncols, chg_bds, changed, nchanged);
      }

      // obtain solution just found by nlp solver

      // Auxiliaries should be correct. solution should be the one found
      // at the node even if not as good as the best known.

      // save violation flag and disregard it while adding cut at NLP
      // point (which are not violated by the current, NLP, solution)
      bool save_av = addviolated_;
      addviolated_ = false;

      // save values
      problem_ -> domain () -> push 
	(problem_ -> nVars (), 
	 problem_ -> domain () -> x  (), 
	 problem_ -> domain () -> lb (), 
	 problem_ -> domain () -> ub (), false);

      // fill originals with nlp values
      if (nlpSol) {
	CoinCopyN (nlpSol, problem_ -> nOrigVars (), problem_ -> domain () -> x ());
      //problem_ -> initAuxs ();

      problem_ -> getAuxs (problem_ -> domain () -> x ());
      }

      if (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING)) {
	jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== genrowcuts on NLP =============\n");
	for (int i = 0; i < problem_ -> nVars (); i++)
	  if (problem_ -> Var (i) -> Multiplicity () > 0)
	    jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
			   problem_ -> X  (i),
			   problem_ -> Lb (i),
			   problem_ -> Ub (i));
	jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
      }

      problem_ -> domain () -> current () -> isNlp () = true;
      genRowCuts (si, cs, nchanged, changed, chg_bds);  // add cuts

      problem_ -> domain () -> pop (); // restore point

      addviolated_ = save_av;     // restore previous value

      //    if (!firstcall_) // keep solution if called from extractLinearRelaxation()
      if (babInfo) 
	babInfo -> setHasNlpSolution (false); // reset it after use //AW HERE

    } else {

      if (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING)) {
	jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== genrowcuts on LP =============\n");
	for (int i = 0; i < problem_ -> nVars (); i++)
	  if (problem_ -> Var (i) -> Multiplicity () > 0)
	    jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
			   problem_ -> X  (i),
			   problem_ -> Lb (i),
			   problem_ -> Ub (i));
	jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
      }

      genRowCuts (si, cs, nchanged, changed, chg_bds);
    }

    // change tightened bounds through OsiCuts
    if (nchanged)
      genColCuts (si, cs, nchanged, changed);

    if (firstcall_ && (cs.sizeRowCuts () >= 1))
      jnlst_->Printf(J_ITERSUMMARY, J_CONVEXIFYING,
		     "Couenne: %d initial row cuts\n", cs.sizeRowCuts ());

    if (realOpt && // this is a good time to check if we have cut the optimal solution
	isOptimumCut (realOpt, cs, problem_))
      jnlst_->Printf(J_ITERSUMMARY, J_CONVEXIFYING,
		     "Warning: Optimal solution was cut\n");
  }

  catch (int exception) {

    if ((exception == infeasible) && (!firstcall_)) {

      jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,
			"Couenne: Infeasible node\n");

      WipeMakeInfeas (cs);
    }

    if (babInfo) // set infeasibility to true in order to skip NLP heuristic
      babInfo -> setInfeasibleNode ();
  }

  delete [] chg_bds;

  if (changed) 
    free (changed);

  if (firstcall_) {

    jnlst_ -> Printf (J_SUMMARY, J_CONVEXIFYING, 
		      "Couenne: %d cuts (%d row, %d col) for linearization\n", 
		      cs.sizeRowCuts () + cs.sizeColCuts (),
		      cs.sizeRowCuts (),  cs.sizeColCuts ());

    fictitiousBound (cs, problem_, true);
    firstcall_  = false;
    ntotalcuts_ = nrootcuts_ = cs.sizeRowCuts ();

  } else { 

    problem_ -> domain () -> pop ();

    ntotalcuts_ += (cs.sizeRowCuts () - nInitCuts);

    if (saveOptimum)
      realOpt = saveOptimum; // restore debug optimum
  }

  septime_ += CoinCpuTime () - now;

  if (jnlst_ -> ProduceOutput (J_ITERSUMMARY, J_CONVEXIFYING)) {

    if (cs.sizeColCuts ()) {
      jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne col cuts:\n");
      for (int i=0; i<cs.sizeColCuts (); i++) 
	cs.colCutPtr (i) -> print ();
    }
  }

  if (!(info.inTree)) 
    rootTime_ = CoinCpuTime ();
}