12 #include "CoinTime.hpp"
22 using namespace Ipopt;
23 using namespace Couenne;
29 OsiSolverInterface *solver);
33 double distance (
const double *p1,
const double *p2,
int size,
double k=2.) {
42 element = *p1++ - *p2++;
43 result += element * element;
49 element = *p1++ - *p2++;
50 result += pow (element,
k);
53 return pow (result, 1. /
k);
69 int CouenneChooseStrong::doStrongBranching (OsiSolverInterface *solver,
70 OsiBranchingInformation *
info,
71 int numberToDo,
int returnCriterion) {
75 if(problem_->doPrint_) {
77 printf(
"doSB: beg: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
78 pv, solver->getColSolution()[pv], solver->getColLower()[pv], solver->getColUpper()[pv]);
79 printf(
"doSB: info: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
80 pv, info->solution_[pv], info->lower_[pv], info->upper_[pv]);
81 printf(
"doSB: problem: lb: %10.4f ub: %10.4f\n",
82 problem_->Lb(pv), problem_->Ub(pv));
88 "\n-\n------- CCS: trying %d objects:\n", numberToDo);
92 int numberColumns = solver -> getNumCols ();
94 solver -> markHotStart ();
98 *initLower = info -> lower_,
99 *initUpper = info -> upper_;
103 *saveLower = CoinCopyOfArray (info -> lower_, numberColumns),
104 *saveUpper = CoinCopyOfArray (info -> upper_, numberColumns),
111 *unionLower =
new double [numberColumns],
112 *unionUpper =
new double [numberColumns],
115 timeStart = CoinCpuTime ();
117 if (jnlst_ -> ProduceOutput (J_DETAILED,
J_BRANCHING)) {
118 Lower0 = CoinCopyOfArray (info -> lower_, numberColumns);
119 Upper0 = CoinCopyOfArray (info -> upper_, numberColumns);
124 lpSol = CoinCopyOfArray (info -> solution_, numberColumns);
135 int returnCode = 0, iDo = 0;
137 for (iDo = 0; iDo < numberToDo; iDo++) {
141 OsiObject *Object = solver_ -> objects () [result -> whichObject ()];
153 OsiBranchingObject * branch = result -> branchingObject ();
154 assert (branch->numberBranches()==2);
158 if (cb) cb -> setSimulate (
true);
173 double indUb = 0, indLb = 0;
175 OsiSimpleInteger *simpl = dynamic_cast <OsiSimpleInteger *>(solver_->objects()[result->whichObject ()]);
180 int objVarIndex = -1;
185 objVarIndex = Object->columnNumber();
188 if(objVarIndex >= 0) {
189 indUb = solver->getColUpper()[objVarIndex];
190 indLb = solver->getColLower()[objVarIndex];
191 if(info->solution_[objVarIndex] < indLb) {
194 if(info->solution_[objVarIndex] > indUb) {
201 status0 = simulateBranch (Object, info, branch, solver, result, -1);
205 result->setDownStatus(1);
211 CoinCopyN (solver->getColLower(), numberColumns, unionLower);
212 CoinCopyN (solver->getColUpper(), numberColumns, unionUpper);
215 for (
int j=0;
j<numberColumns;
j++) {
216 if(problem_->Lb(
j) > unionLower[
j]) {
217 unionLower[
j] = problem_->Lb(
j);
219 if(problem_->Ub(
j) < unionLower[
j]) {
220 unionLower[
j] = problem_->Ub(
j);
223 solver->setColLower(
j, saveLower [
j]);
224 solver->setColUpper (j, saveUpper [j]);
225 problem_ -> Lb (j) = saveLower [
j];
226 problem_ -> Ub (j) = saveUpper [
j];
231 status1 = simulateBranch (Object, info, branch, solver, result, +1);
235 result->setUpStatus(1);
239 if(problem_->doPrint_) {
240 printf(
"Strong on object %d: status0: %d status1: %d\n",
241 result->whichObject(), status0, status1);
247 jnlst_ -> Printf (J_ITERSUMMARY,
J_BRANCHING,
"-------\n");
250 cb -> setSimulate (
false);
254 bool tightened =
false;
258 const double *sLb = solver->getColLower();
259 const double *sUb = solver->getColUpper();
263 for (
int j=0;
j<numberColumns;
j++) {
264 double maxLb = (problem_->Lb(
j) < sLb[
j] ? sLb[
j] : problem_->Lb(
j));
265 double minUb = (problem_->Ub(
j) < sUb[
j] ? problem_->Ub(
j) : sUb[
j]);
266 problem_->Lb(
j) = (unionLower[
j] > maxLb ? maxLb : unionLower [
j]);
267 problem_->Ub(
j) = (unionUpper[
j] < minUb ? minUb : unionUpper [
j]);
271 for (
int j=0;
j<numberColumns;
j++) {
272 problem_->Lb(
j) = (problem_->Lb(
j) < sLb[
j] ? sLb[
j] : problem_->Lb(
j));
273 problem_->Ub(
j) = (problem_->Ub(
j) < sUb[
j] ? problem_->Ub(
j) : sUb[
j]);
280 for (
int j=0;
j<numberColumns;
j++) {
281 problem_->Lb (
j) = unionLower [
j];
282 problem_->Ub (
j) = unionUpper [
j];
287 if((status0 == 1) && (status1 == 1)) {
292 double lbVar0 = solver->getColLower()[0];
294 solver->setColLower(0, 1);
295 solver->setColUpper(0, 0);
298 solver->setColUpper(0, lbVar0-1);
302 for (
int j=0;
j<numberColumns;
j++) {
304 chg_bds [
j].
setLower (t_chg_bounds::CHANGED);
309 chg_bds [
j].
setUpper (t_chg_bounds::CHANGED);
315 (problem_ -> doFBBT ()) &&
316 !(problem_ -> btCore (chg_bds)))
318 status0 = status1 = 1;
322 if ((status0 != 1) || (status1 != 1)) {
326 for (
int j=0;
j<numberColumns;
j++) {
327 solver -> setColLower (
j, saveLower [
j] = problem_ -> Lb (
j));
328 solver -> setColUpper (
j, saveUpper [
j] = problem_ -> Ub (
j));
351 }
else if (status0==1 || status1==1) {
354 if (problem_ -> orbitalBranching () &&
355 (Object -> columnNumber () >= 0) &&
356 (problem_ -> Find_Orbit (Object -> columnNumber ()) -> size () > 1)) {
358 problem_ -> ChangeBounds (solver -> getColLower (),
359 solver -> getColUpper (),
360 problem_ -> nVars ());
362 problem_ -> Compute_Symmetry ();
366 numberStrongFixed_++;
367 if (!returnCriterion) {
375 bool hitMaxTime = ( CoinCpuTime()-timeStart > info->timeRemaining_);
382 if (jnlst_ -> ProduceOutput (J_DETAILED,
J_BRANCHING)) {
383 printf (
"strong branching: tightened bounds. ");
385 for (
int j=0;
j<numberColumns;
j++) {
387 if (problem_ -> Lb (
j) > Lower0 [
j]) printf (
"l%d (%g-->%g) ", j,Lower0[j], problem_->Lb (j));
388 if (problem_ -> Ub (j) < Upper0 [
j]) printf (
"u%d (%g-->%g) ", j,Upper0[j], problem_->Ub (j));
399 jnlst_ -> Printf (J_ITERSUMMARY,
J_BRANCHING,
"----------------------done\n\n\n");
402 if(problem_->doPrint_) {
404 printf(
"doSB: beg: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
405 pv, solver->getColSolution()[pv], solver->getColLower()[pv], solver->getColUpper()[pv]);
406 printf(
"doSB: info: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
407 pv, info->solution_[pv], info->lower_[pv], info->upper_[pv]);
408 printf(
"doSB: problem: lb: %10.4f ub: %10.4f\n",
409 problem_->Lb(pv), problem_->Ub(pv));
414 if (iDo < numberToDo) iDo++;
415 assert (iDo <= (
int) results_.size());
416 results_.resize (iDo);
418 delete [] unionLower;
419 delete [] unionUpper;
424 solver -> unmarkHotStart ();
427 branchtime_ += CoinCpuTime () - timeStart;
429 jnlst_ -> Printf (J_DETAILED,
J_BRANCHING,
"Done doStrongBranching\n");
436 int CouenneChooseStrong::simulateBranch (OsiObject *Object,
437 OsiBranchingInformation *
info,
438 OsiBranchingObject *branch,
439 OsiSolverInterface *solver,
443 bool boundBranch = branch -> boundBranch ();
449 OsiSolverInterface *thisSolver =
450 boundBranch ? solver : solver -> clone ();
457 (!CouObj && !
BranchingFBBT (problem_, Object, thisSolver))) {
461 if (direction < 0) result -> setDownStatus (1);
462 else result -> setUpStatus (1);
468 thisSolver -> solveFromHotStart ();
473 thisSolver -> getIntParam (OsiMaxNumIterationHotStart, limit);
474 thisSolver -> setIntParam (OsiMaxNumIteration, limit);
476 thisSolver -> resolve ();
478 CouObj -> setEstimate (
COUENNE_EPS, direction < 0 ? 0 : 1);
481 if (pseudoUpdateLP_ && CouObj && thisSolver -> isProvenOptimal ()) {
483 problem_ -> nVars ());
486 CouObj -> setEstimate (dist, direction < 0 ? 0 : 1);
495 status = result -> updateInformation (thisSolver, info,
this);
497 numberStrongIterations_ += thisSolver -> getIterationCount ();
499 if ((status == 3) && (trustStrongForSolution_)) {
501 info -> cutoff_ = goodObjectiveValue_;
506 if (solver != thisSolver)
516 OsiSolverInterface *solver) {
518 bool feasible =
true;
520 if (problem -> doFBBT ()) {
522 problem -> domain () -> push (solver);
525 indVar = Object -> columnNumber (),
526 nvars = problem -> nVars ();
535 chg_bds [indVar].
setUpper (t_chg_bounds::CHANGED);
536 chg_bds [indVar].
setLower (t_chg_bounds::CHANGED);
538 problem -> installCutOff ();
540 if ((feasible = problem -> btCore (chg_bds))) {
543 *lb = solver -> getColLower (),
544 *ub = solver -> getColUpper (),
545 *nLB = problem -> Lb (),
546 *nUB = problem -> Ub ();
548 for (
int i=0; i<nvars; i++) {
549 if (nLB [i] > lb [i]) solver -> setColLower (i, nLB [i]);
550 if (nUB [i] < ub [i]) solver -> setColUpper (i, nUB [i]);
557 problem -> domain () -> pop ();
bool BranchingFBBT(CouenneProblem *problem, OsiObject *Object, OsiSolverInterface *solver)
Called from simulateBranch and from disjunctive cut generators when object is not CouenneObject and t...
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real fint fint fint fint * info
OsiObject for auxiliary variables $w=f(x)$.
status of lower/upper bound of a variable, to be checked/modified in bound tightening ...
void setLower(ChangeStatus lower)
"Spatial" branching object.
const Ipopt::EJournalCategory J_BRANCHING(Ipopt::J_USER1)
void setUpper(ChangeStatus upper)
Class for MINLP problems with symbolic information.
double CouNumber
main number type in Couenne
int Index() const
Get variable index in problem.
exprVar * Reference() const
return reference auxiliary variable
double distance(const double *p1, const double *p2, int size, double k=2.)
compute Euclidean distance between two points (most likely LP solutions) l_2 norm by default...