Skip to content

Commit d06f5c0

Browse files
committed
put strong branching into lambda function
1 parent be50c23 commit d06f5c0

File tree

1 file changed

+67
-157
lines changed

1 file changed

+67
-157
lines changed

highs/mip/HighsSearch.cpp

Lines changed: 67 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -530,18 +530,13 @@ HighsInt HighsSearch::selectBranchingCandidate(int64_t maxSbIters,
530530
}
531531
};
532532

533-
if (!downscorereliable[candidate] &&
534-
(upscorereliable[candidate] ||
535-
std::make_pair(downscore[candidate],
536-
pseudocost.getAvgInferencesDown(col)) >=
537-
std::make_pair(upscore[candidate],
538-
pseudocost.getAvgInferencesUp(col)))) {
539-
// evaluate down branch
540-
// if (!mipsolver.submip)
541-
// printf("down eval col=%d fracval=%g\n", col, fracval);
533+
auto strongBranch = [&](bool upbranch) {
542534
int64_t inferences = -(int64_t)localdom.getDomainChangeStack().size() - 1;
535+
HighsBoundType boundtype = upbranch ? HighsBoundType::kLower
536+
: HighsBoundType::kUpper;
537+
double boundval = upbranch ? upval : downval;
538+
HighsDomainChange domchg{boundval, col, boundtype};
543539

544-
HighsDomainChange domchg{downval, col, HighsBoundType::kUpper};
545540
bool orbitalFixing =
546541
nodestack.back().stabilizerOrbits && orbitsValidInChildNode(domchg);
547542
localdom.changeBound(domchg);
@@ -557,19 +552,24 @@ HighsInt HighsSearch::selectBranchingCandidate(int64_t maxSbIters,
557552
inferences += localdom.getDomainChangeStack().size();
558553
if (localdom.infeasible()) {
559554
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool);
560-
pseudocost.addCutoffObservation(col, false);
555+
pseudocost.addCutoffObservation(col, upbranch);
561556
localdom.backtrack();
562557
localdom.clearChangedCols();
563558

564-
branchUpwards(col, upval, fracval);
559+
if (upbranch) {
560+
branchDownwards(col, downval, fracval);
561+
}
562+
else {
563+
branchUpwards(col, upval, fracval);
564+
}
565565
nodestack[nodestack.size() - 2].opensubtrees = 0;
566566
nodestack[nodestack.size() - 2].skipDepthCount = 1;
567567
depthoffset -= 1;
568568

569-
return -1;
569+
return true;
570570
}
571571

572-
pseudocost.addInferenceObservation(col, inferences, false);
572+
pseudocost.addInferenceObservation(col, inferences, upbranch);
573573

574574
int64_t numiters = lp->getNumLpIterations();
575575
HighsLpRelaxation::Status status = playground.solveLp(localdom);
@@ -580,18 +580,24 @@ HighsInt HighsSearch::selectBranchingCandidate(int64_t maxSbIters,
580580
if (lp->scaledOptimal(status)) {
581581
lp->performAging();
582582

583-
double delta = downval - fracval;
583+
double delta = upbranch ? upval - fracval : downval - fracval;
584584
bool integerfeasible;
585585
const std::vector<double>& sol = lp->getSolution().col_value;
586586
double solobj = checkSol(sol, integerfeasible);
587587

588588
double objdelta = std::max(solobj - lp->getObjective(), 0.0);
589589
if (objdelta <= mipsolver.mipdata_->epsilon) objdelta = 0.0;
590590

591-
downscore[candidate] = objdelta;
592-
downscorereliable[candidate] = true;
593-
594-
markBranchingVarDownReliableAtNode(col);
591+
if (upbranch) {
592+
upscore[candidate] = objdelta;
593+
upscorereliable[candidate] = true;
594+
markBranchingVarUpReliableAtNode(col);
595+
}
596+
else {
597+
downscore[candidate] = objdelta;
598+
downscorereliable[candidate] = true;
599+
markBranchingVarDownReliableAtNode(col);
600+
}
595601
pseudocost.addObservation(col, delta, objdelta);
596602
analyzeSolution(objdelta, sol);
597603

@@ -607,7 +613,12 @@ HighsInt HighsSearch::selectBranchingCandidate(int64_t maxSbIters,
607613
}
608614

609615
if (lp->unscaledDualFeasible(status)) {
610-
downbound[candidate] = solobj;
616+
if (upbranch) {
617+
upbound[candidate] = solobj;
618+
}
619+
else {
620+
downbound[candidate] = solobj;
621+
}
611622
if (solobj > mipsolver.mipdata_->optimality_limit) {
612623
addBoundExceedingConflict();
613624

@@ -617,13 +628,18 @@ HighsInt HighsSearch::selectBranchingCandidate(int64_t maxSbIters,
617628
localdom.backtrack();
618629
lp->flushDomain(localdom);
619630

620-
branchUpwards(col, upval, fracval);
631+
if (upbranch) {
632+
branchDownwards(col, downval, fracval);
633+
}
634+
else {
635+
branchUpwards(col, upval, fracval);
636+
}
621637
nodestack[nodestack.size() - 2].opensubtrees = pruned ? 0 : 1;
622638
nodestack[nodestack.size() - 2].other_child_lb = solobj;
623639
nodestack[nodestack.size() - 2].skipDepthCount = 1;
624640
depthoffset -= 1;
625641

626-
return -1;
642+
return true;
627643
}
628644
} else if (solobj > getCutoffBound()) {
629645
addBoundExceedingConflict();
@@ -633,27 +649,37 @@ HighsInt HighsSearch::selectBranchingCandidate(int64_t maxSbIters,
633649
localdom.backtrack();
634650
lp->flushDomain(localdom);
635651

636-
branchUpwards(col, upval, fracval);
652+
if (upbranch) {
653+
branchDownwards(col, downval, fracval);
654+
}
655+
else {
656+
branchUpwards(col, upval, fracval);
657+
}
637658
nodestack[nodestack.size() - 2].opensubtrees = 0;
638659
nodestack[nodestack.size() - 2].skipDepthCount = 1;
639660
depthoffset -= 1;
640661

641-
return -1;
662+
return true;
642663
}
643664
}
644665
} else if (status == HighsLpRelaxation::Status::kInfeasible) {
645666
mipsolver.mipdata_->debugSolution.nodePruned(localdom);
646667
addInfeasibleConflict();
647-
pseudocost.addCutoffObservation(col, false);
668+
pseudocost.addCutoffObservation(col, upbranch);
648669
localdom.backtrack();
649670
lp->flushDomain(localdom);
650671

651-
branchUpwards(col, upval, fracval);
672+
if (upbranch) {
673+
branchDownwards(col, downval, fracval);
674+
}
675+
else {
676+
branchUpwards(col, upval, fracval);
677+
}
652678
nodestack[nodestack.size() - 2].opensubtrees = 0;
653679
nodestack[nodestack.size() - 2].skipDepthCount = 1;
654680
depthoffset -= 1;
655681

656-
return -1;
682+
return true;
657683
} else {
658684
// printf("todo2\n");
659685
// in case of an LP error we set the score of this variable to zero to
@@ -668,140 +694,24 @@ HighsInt HighsSearch::selectBranchingCandidate(int64_t maxSbIters,
668694

669695
localdom.backtrack();
670696
lp->flushDomain(localdom);
697+
return false;
698+
};
699+
700+
if (!downscorereliable[candidate] &&
701+
(upscorereliable[candidate] ||
702+
std::make_pair(downscore[candidate],
703+
pseudocost.getAvgInferencesDown(col)) >=
704+
std::make_pair(upscore[candidate],
705+
pseudocost.getAvgInferencesUp(col)))) {
706+
// evaluate down branch
707+
// if (!mipsolver.submip)
708+
// printf("down eval col=%d fracval=%g\n", col, fracval);
709+
if (strongBranch(false)) return -1;
671710
} else {
672711
// if (!mipsolver.submip)
673712
// printf("up eval col=%d fracval=%g\n", col, fracval);
674713
// evaluate up branch
675-
int64_t inferences = -(int64_t)localdom.getDomainChangeStack().size() - 1;
676-
HighsDomainChange domchg{upval, col, HighsBoundType::kLower};
677-
bool orbitalFixing =
678-
nodestack.back().stabilizerOrbits && orbitsValidInChildNode(domchg);
679-
localdom.changeBound(domchg);
680-
localdom.propagate();
681-
682-
if (!localdom.infeasible()) {
683-
if (orbitalFixing)
684-
nodestack.back().stabilizerOrbits->orbitalFixing(localdom);
685-
else
686-
mipsolver.mipdata_->symmetries.propagateOrbitopes(localdom);
687-
}
688-
689-
inferences += localdom.getDomainChangeStack().size();
690-
if (localdom.infeasible()) {
691-
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool);
692-
pseudocost.addCutoffObservation(col, true);
693-
localdom.backtrack();
694-
localdom.clearChangedCols();
695-
696-
branchDownwards(col, downval, fracval);
697-
nodestack[nodestack.size() - 2].opensubtrees = 0;
698-
nodestack[nodestack.size() - 2].skipDepthCount = 1;
699-
depthoffset -= 1;
700-
701-
return -1;
702-
}
703-
704-
pseudocost.addInferenceObservation(col, inferences, true);
705-
706-
int64_t numiters = lp->getNumLpIterations();
707-
HighsLpRelaxation::Status status = playground.solveLp(localdom);
708-
numiters = lp->getNumLpIterations() - numiters;
709-
lpiterations += numiters;
710-
sblpiterations += numiters;
711-
712-
if (lp->scaledOptimal(status)) {
713-
lp->performAging();
714-
715-
double delta = upval - fracval;
716-
bool integerfeasible;
717-
718-
const std::vector<double>& sol =
719-
lp->getLpSolver().getSolution().col_value;
720-
double solobj = checkSol(sol, integerfeasible);
721-
722-
double objdelta = std::max(solobj - lp->getObjective(), 0.0);
723-
if (objdelta <= mipsolver.mipdata_->epsilon) objdelta = 0.0;
724-
725-
upscore[candidate] = objdelta;
726-
upscorereliable[candidate] = true;
727-
728-
markBranchingVarUpReliableAtNode(col);
729-
pseudocost.addObservation(col, delta, objdelta);
730-
analyzeSolution(objdelta, sol);
731-
732-
if (lp->unscaledPrimalFeasible(status) && integerfeasible) {
733-
double cutoffbnd = getCutoffBound();
734-
mipsolver.mipdata_->addIncumbent(
735-
lp->getLpSolver().getSolution().col_value, solobj,
736-
inheuristic ? kSolutionSourceHeuristic
737-
: kSolutionSourceBranching);
738-
739-
if (mipsolver.mipdata_->upper_limit < cutoffbnd)
740-
lp->setObjectiveLimit(mipsolver.mipdata_->upper_limit);
741-
}
742-
743-
if (lp->unscaledDualFeasible(status)) {
744-
upbound[candidate] = solobj;
745-
if (solobj > mipsolver.mipdata_->optimality_limit) {
746-
addBoundExceedingConflict();
747-
748-
bool pruned = solobj > getCutoffBound();
749-
if (pruned) mipsolver.mipdata_->debugSolution.nodePruned(localdom);
750-
751-
localdom.backtrack();
752-
lp->flushDomain(localdom);
753-
754-
branchDownwards(col, downval, fracval);
755-
nodestack[nodestack.size() - 2].opensubtrees = pruned ? 0 : 1;
756-
nodestack[nodestack.size() - 2].other_child_lb = solobj;
757-
nodestack[nodestack.size() - 2].skipDepthCount = 1;
758-
depthoffset -= 1;
759-
760-
return -1;
761-
}
762-
} else if (solobj > getCutoffBound()) {
763-
addBoundExceedingConflict();
764-
localdom.propagate();
765-
bool infeas = localdom.infeasible();
766-
if (infeas) {
767-
localdom.backtrack();
768-
lp->flushDomain(localdom);
769-
770-
branchDownwards(col, downval, fracval);
771-
nodestack[nodestack.size() - 2].opensubtrees = 0;
772-
nodestack[nodestack.size() - 2].skipDepthCount = 1;
773-
depthoffset -= 1;
774-
775-
return -1;
776-
}
777-
}
778-
} else if (status == HighsLpRelaxation::Status::kInfeasible) {
779-
mipsolver.mipdata_->debugSolution.nodePruned(localdom);
780-
addInfeasibleConflict();
781-
pseudocost.addCutoffObservation(col, true);
782-
localdom.backtrack();
783-
lp->flushDomain(localdom);
784-
785-
branchDownwards(col, downval, fracval);
786-
nodestack[nodestack.size() - 2].opensubtrees = 0;
787-
nodestack[nodestack.size() - 2].skipDepthCount = 1;
788-
depthoffset -= 1;
789-
790-
return -1;
791-
} else {
792-
// printf("todo2\n");
793-
// in case of an LP error we set the score of this variable to zero to
794-
// avoid choosing it as branching candidate if possible
795-
downscore[candidate] = 0.0;
796-
upscore[candidate] = 0.0;
797-
downscorereliable[candidate] = 1;
798-
upscorereliable[candidate] = 1;
799-
markBranchingVarUpReliableAtNode(col);
800-
markBranchingVarDownReliableAtNode(col);
801-
}
802-
803-
localdom.backtrack();
804-
lp->flushDomain(localdom);
714+
if (strongBranch(true)) return -1;
805715
}
806716
}
807717
}

0 commit comments

Comments
 (0)