// Creates a branching object CbcBranchingObject * CbcSimpleIntegerFixed::createBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) { const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); assert (upper[columnNumber_]>lower[columnNumber_]); if (!model_->hotstartSolution()) { double nearest = floor(value+0.5); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); if (fabs(value-nearest)<integerTolerance) { // adjust value if (nearest!=upper[columnNumber_]) value = nearest+2.0*integerTolerance; else value = nearest-2.0*integerTolerance; } } else { const double * hotstartSolution = model_->hotstartSolution(); double targetValue = hotstartSolution[columnNumber_]; if (way>0) value = targetValue-0.1; else value = targetValue+0.1; } CbcBranchingObject * branch = new CbcIntegerBranchingObject(model_,columnNumber_,way, value); branch->setOriginalObject(this); return branch; }
CbcBranchingObject * CbcNWay::createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * /*info*/, int /*way*/) { int numberFree = 0; int j; //OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); int * list = new int[numberMembers_]; double * sort = new double[numberMembers_]; for (j = 0; j < numberMembers_; j++) { int iColumn = members_[j]; double value = solution[iColumn]; value = CoinMax(value, lower[iColumn]); value = CoinMin(value, upper[iColumn]); if (upper[iColumn] > lower[iColumn]) { double distance = upper[iColumn] - value; list[numberFree] = j; sort[numberFree++] = distance; } } assert (numberFree); // sort CoinSort_2(sort, sort + numberFree, list); // create object CbcBranchingObject * branch; branch = new CbcNWayBranchingObject(model_, this, numberFree, list); branch->setOriginalObject(this); delete [] list; delete [] sort; return branch; }
int CbcBranchDefaultDecision::bestBranch (CbcBranchingObject ** objects, int numberObjects, int numberUnsatisfied, double * changeUp, int * numberInfeasibilitiesUp, double * changeDown, int * numberInfeasibilitiesDown, double objectiveValue) { int bestWay = 0; int whichObject = -1; if (numberObjects) { CbcModel * model = cbcModel(); // at continuous //double continuousObjective = model->getContinuousObjective(); //int continuousInfeasibilities = model->getContinuousInfeasibilities(); // average cost to get rid of infeasibility //double averageCostPerInfeasibility = //(objectiveValue-continuousObjective)/ //(double) (abs(continuousInfeasibilities-numberUnsatisfied)+1); /* beforeSolution is : 0 - before any solution n - n heuristic solutions but no branched one -1 - branched solution found */ int numberSolutions = model->getSolutionCount(); double cutoff = model->getCutoff(); int method = 0; int i; if (numberSolutions) { int numberHeuristic = model->getNumberHeuristicSolutions(); if (numberHeuristic < numberSolutions) { method = 1; } else { method = 2; // look further for ( i = 0 ; i < numberObjects ; i++) { int numberNext = numberInfeasibilitiesUp[i]; if (numberNext < numberUnsatisfied) { int numberUp = numberUnsatisfied - numberInfeasibilitiesUp[i]; double perUnsatisfied = changeUp[i] / static_cast<double> (numberUp); double estimatedObjective = objectiveValue + numberUnsatisfied * perUnsatisfied; if (estimatedObjective < cutoff) method = 3; } numberNext = numberInfeasibilitiesDown[i]; if (numberNext < numberUnsatisfied) { int numberDown = numberUnsatisfied - numberInfeasibilitiesDown[i]; double perUnsatisfied = changeDown[i] / static_cast<double> (numberDown); double estimatedObjective = objectiveValue + numberUnsatisfied * perUnsatisfied; if (estimatedObjective < cutoff) method = 3; } } } method = 2; } else { method = 0; } // Uncomment next to force method 4 //method=4; // FIXME This should be an enum. It will be easier to // understand in the code than numbers. /* Methods : 0 - fewest infeasibilities 1 - largest min change in objective 2 - as 1 but use sum of changes if min close 3 - predicted best solution 4 - take cheapest up branch if infeasibilities same */ int bestNumber = COIN_INT_MAX; double bestCriterion = -1.0e50; double alternativeCriterion = -1.0; double bestEstimate = 1.0e100; switch (method) { case 0: // could add in depth as well for ( i = 0 ; i < numberObjects ; i++) { int thisNumber = CoinMin(numberInfeasibilitiesUp[i], numberInfeasibilitiesDown[i]); if (thisNumber <= bestNumber) { int betterWay = 0; if (numberInfeasibilitiesUp[i] < numberInfeasibilitiesDown[i]) { if (numberInfeasibilitiesUp[i] < bestNumber) { betterWay = 1; } else { if (changeUp[i] < bestCriterion) betterWay = 1; } } else if (numberInfeasibilitiesUp[i] > numberInfeasibilitiesDown[i]) { if (numberInfeasibilitiesDown[i] < bestNumber) { betterWay = -1; } else { if (changeDown[i] < bestCriterion) betterWay = -1; } } else { // up and down have same number bool better = false; if (numberInfeasibilitiesUp[i] < bestNumber) { better = true; } else if (numberInfeasibilitiesUp[i] == bestNumber) { if (CoinMin(changeUp[i], changeDown[i]) < bestCriterion) better = true;; } if (better) { // see which way if (changeUp[i] <= changeDown[i]) betterWay = 1; else betterWay = -1; } } if (betterWay) { bestCriterion = CoinMin(changeUp[i], changeDown[i]); bestNumber = thisNumber; whichObject = i; bestWay = betterWay; } } } break; case 1: for ( i = 0 ; i < numberObjects ; i++) { int betterWay = 0; if (changeUp[i] <= changeDown[i]) { if (changeUp[i] > bestCriterion) betterWay = 1; } else { if (changeDown[i] > bestCriterion) betterWay = -1; } if (betterWay) { bestCriterion = CoinMin(changeUp[i], changeDown[i]); whichObject = i; bestWay = betterWay; } } break; case 2: for ( i = 0 ; i < numberObjects ; i++) { double change = CoinMin(changeUp[i], changeDown[i]); double sum = changeUp[i] + changeDown[i]; bool take = false; if (change > 1.1*bestCriterion) take = true; else if (change > 0.9*bestCriterion && sum + change > bestCriterion + alternativeCriterion) take = true; if (take) { if (changeUp[i] <= changeDown[i]) { if (changeUp[i] > bestCriterion) bestWay = 1; } else { if (changeDown[i] > bestCriterion) bestWay = -1; } bestCriterion = change; alternativeCriterion = sum; whichObject = i; } } break; case 3: for ( i = 0 ; i < numberObjects ; i++) { int numberNext = numberInfeasibilitiesUp[i]; if (numberNext < numberUnsatisfied) { int numberUp = numberUnsatisfied - numberInfeasibilitiesUp[i]; double perUnsatisfied = changeUp[i] / static_cast<double> (numberUp); double estimatedObjective = objectiveValue + numberUnsatisfied * perUnsatisfied; if (estimatedObjective < bestEstimate) { bestEstimate = estimatedObjective; bestWay = 1; whichObject = i; } } numberNext = numberInfeasibilitiesDown[i]; if (numberNext < numberUnsatisfied) { int numberDown = numberUnsatisfied - numberInfeasibilitiesDown[i]; double perUnsatisfied = changeDown[i] / static_cast<double> (numberDown); double estimatedObjective = objectiveValue + numberUnsatisfied * perUnsatisfied; if (estimatedObjective < bestEstimate) { bestEstimate = estimatedObjective; bestWay = -1; whichObject = i; } } } break; case 4: // if number infeas same then cheapest up // first get best number or when going down // now choose smallest change up amongst equal number infeas for ( i = 0 ; i < numberObjects ; i++) { int thisNumber = CoinMin(numberInfeasibilitiesUp[i], numberInfeasibilitiesDown[i]); if (thisNumber <= bestNumber) { int betterWay = 0; if (numberInfeasibilitiesUp[i] < numberInfeasibilitiesDown[i]) { if (numberInfeasibilitiesUp[i] < bestNumber) { betterWay = 1; } else { if (changeUp[i] < bestCriterion) betterWay = 1; } } else if (numberInfeasibilitiesUp[i] > numberInfeasibilitiesDown[i]) { if (numberInfeasibilitiesDown[i] < bestNumber) { betterWay = -1; } else { if (changeDown[i] < bestCriterion) betterWay = -1; } } else { // up and down have same number bool better = false; if (numberInfeasibilitiesUp[i] < bestNumber) { better = true; } else if (numberInfeasibilitiesUp[i] == bestNumber) { if (CoinMin(changeUp[i], changeDown[i]) < bestCriterion) better = true;; } if (better) { // see which way if (changeUp[i] <= changeDown[i]) betterWay = 1; else betterWay = -1; } } if (betterWay) { bestCriterion = CoinMin(changeUp[i], changeDown[i]); bestNumber = thisNumber; whichObject = i; bestWay = betterWay; } } } bestCriterion = 1.0e50; for ( i = 0 ; i < numberObjects ; i++) { int thisNumber = numberInfeasibilitiesUp[i]; if (thisNumber == bestNumber && changeUp) { if (changeUp[i] < bestCriterion) { bestCriterion = changeUp[i]; whichObject = i; bestWay = 1; } } } break; } // set way in best if (whichObject >= 0) { CbcBranchingObject * bestObject = objects[whichObject]; if (bestObject->object() && bestObject->object()->preferredWay()) bestWay = bestObject->object()->preferredWay(); bestObject->way(bestWay); } else { COIN_DETAIL_PRINT(printf("debug\n")); } } return whichObject; }