Skip to content

Commit 8232b5e

Browse files
committed
attempt
1 parent 6d77072 commit 8232b5e

File tree

3 files changed

+202
-3
lines changed

3 files changed

+202
-3
lines changed

highs/mip/HighsMipSolver.cpp

Lines changed: 179 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,6 @@ void HighsMipSolver::run() {
292292
double lowerBoundLastCheck = mipdata_->lower_bound;
293293
analysis_.mipTimerStart(kMipClockSearch);
294294

295-
int k = 0;
296-
297295
// Initialize worker relaxations and mipworkers
298296
// todo lps and workers are still empty right now
299297

@@ -303,7 +301,11 @@ void HighsMipSolver::run() {
303301
mipdata_->workers.emplace_back(*this, mipdata_->lps.back());
304302
}
305303

304+
int k = 0;
305+
306306
while (search.hasNode()) {
307+
308+
if (k % 2 == 0) {
307309

308310

309311
// Possibly look for primal solution from the user
@@ -764,10 +766,185 @@ void HighsMipSolver::run() {
764766
analysis_.node_search_time.push_back(this_node_search_time);
765767
}
766768
if (limit_reached) break;
769+
770+
} else {
771+
{
772+
773+
HighsMipWorker& worker = mipdata_->workers.at(1);
774+
HighsSearch& worker_search = *worker.search_ptr_.get();
775+
HighsLpRelaxation& worker_lp_relax = worker.lprelaxation_;
776+
777+
analysis_.mipTimerStart(kMipClockPerformAging1);
778+
worker.conflictpool_.performAging();
779+
// mipdata_.conflictPool_.performAging();
780+
analysis_.mipTimerStop(kMipClockPerformAging1);
781+
// set iteration limit for each lp solve during the dive to 10 times the
782+
// average nodes
783+
784+
HighsInt iterlimit = 10 * std::max(mipdata_->lp.getAvgSolveIters(),
785+
mipdata_->avgrootlpiters);
786+
iterlimit = std::max({HighsInt{10000}, iterlimit,
787+
HighsInt((3 * mipdata_->firstrootlpiters) / 2)});
788+
789+
// mipdata_->lp.setIterationLimit(iterlimit);
790+
worker_lp_relax.setIterationLimit(iterlimit);
791+
792+
793+
// perform the dive and put the open nodes to the queue
794+
size_t plungestart = mipdata_->num_nodes;
795+
bool limit_reached = false;
796+
797+
// atm heuristics in the dive break lseu debug64
798+
// bool considerHeuristics = true;
799+
bool considerHeuristics = false;
800+
801+
analysis_.mipTimerStart(kMipClockDive);
802+
while (true) {
803+
// Possibly apply primal heuristics
804+
// if (considerHeuristics && mipdata_->moreHeuristicsAllowed()) {
805+
// analysis_.mipTimerStart(kMipClockDiveEvaluateNode);
806+
// const HighsSearch::NodeResult evaluate_node_result =
807+
// search.evaluateNode();
808+
// analysis_.mipTimerStop(kMipClockDiveEvaluateNode);
809+
810+
// if (evaluate_node_result == HighsSearch::NodeResult::kSubOptimal) break;
811+
812+
// if (search.currentNodePruned()) {
813+
// // ig: do we update num_leaves here?
814+
// ++mipdata_->num_leaves;
815+
// search.flushStatistics();
816+
// } else {
817+
// analysis_.mipTimerStart(kMipClockDivePrimalHeuristics);
818+
// if (mipdata_->incumbent.empty()) {
819+
// analysis_.mipTimerStart(kMipClockDiveRandomizedRounding);
820+
// mipdata_->heuristics.randomizedRounding(
821+
// master_worker,
822+
// mipdata_->lp.getLpSolver().getSolution().col_value);
823+
// analysis_.mipTimerStop(kMipClockDiveRandomizedRounding);
824+
// }
825+
826+
// if (mipdata_->incumbent.empty()) {
827+
// if (options_mip_->mip_heuristic_run_rens) {
828+
// analysis_.mipTimerStart(kMipClockDiveRens);
829+
// mipdata_->heuristics.RENS(
830+
// master_worker,
831+
// mipdata_->lp.getLpSolver().getSolution().col_value);
832+
// analysis_.mipTimerStop(kMipClockDiveRens);
833+
// }
834+
// } else {
835+
// if (options_mip_->mip_heuristic_run_rins) {
836+
// analysis_.mipTimerStart(kMipClockDiveRins);
837+
// mipdata_->heuristics.RINS(
838+
// master_worker,
839+
// mipdata_->lp.getLpSolver().getSolution().col_value);
840+
// analysis_.mipTimerStop(kMipClockDiveRins);
841+
// }
842+
// }
843+
844+
// mipdata_->heuristics.flushStatistics(master_worker);
845+
// analysis_.mipTimerStop(kMipClockDivePrimalHeuristics);
846+
// }
847+
// }
848+
849+
considerHeuristics = false;
850+
851+
if (mipdata_->domain.infeasible()) break;
852+
853+
if (worker_search.getDomain().infeasible()) continue;
854+
855+
856+
// install node here?
857+
search.installNode(mipdata_->nodequeue.popBestBoundNode());
858+
859+
860+
if (!worker_search.currentNodePruned()) {
861+
double this_dive_time = -analysis_.mipTimerRead(kMipClockTheDive);
862+
analysis_.mipTimerStart(kMipClockTheDive);
863+
const HighsSearch::NodeResult search_dive_result = worker_search.dive();
864+
analysis_.mipTimerStop(kMipClockTheDive);
865+
if (analysis_.analyse_mip_time) {
866+
this_dive_time += analysis_.mipTimerRead(kMipClockNodeSearch);
867+
analysis_.dive_time.push_back(this_dive_time);
868+
}
869+
if (search_dive_result == HighsSearch::NodeResult::kSubOptimal) break;
870+
871+
++mipdata_->num_leaves;
872+
873+
worker_search.flushStatistics();
874+
}
875+
876+
if (mipdata_->checkLimits()) {
877+
limit_reached = true;
878+
break;
879+
}
880+
881+
// disable because it needs nodequeue
882+
// HighsInt numPlungeNodes = mipdata_->num_nodes - plungestart;
883+
// if (numPlungeNodes >= 100) break;
884+
885+
// analysis_.mipTimerStart(kMipClockBacktrackPlunge);
886+
// const bool backtrack_plunge = search.backtrackPlunge(mipdata_->nodequeue);
887+
// analysis_.mipTimerStop(kMipClockBacktrackPlunge);
888+
// if (!backtrack_plunge) break;
889+
890+
891+
assert(worker_search.hasNode());
892+
893+
// if (mipdata_->conflictPool.getNumConflicts() >
894+
if (worker.conflictpool_.getNumConflicts() >
895+
options_mip_->mip_pool_soft_limit) {
896+
analysis_.mipTimerStart(kMipClockPerformAging2);
897+
worker.conflictpool_.performAging();
898+
// mipdata_->conflictPool.performAging();
899+
analysis_.mipTimerStop(kMipClockPerformAging2);
900+
}
901+
902+
worker_search.flushStatistics();
903+
mipdata_->printDisplayLine();
904+
// printf("continue plunging due to good estimate\n");
905+
} // while (true)
906+
analysis_.mipTimerStop(kMipClockDive);
907+
908+
analysis_.mipTimerStart(kMipClockOpenNodesToQueue0);
909+
910+
// needs sync
911+
// maybe there should be a nodequeue in the search after all
912+
worker.syncNodeQueue(mipdata_->nodequeue);
913+
914+
// search.openNodesToQueue(mipdata_->nodequeue);
915+
analysis_.mipTimerStop(kMipClockOpenNodesToQueue0);
916+
917+
worker_search.flushStatistics();
918+
919+
// if (limit_reached) {
920+
// double prev_lower_bound = mipdata_->lower_bound;
921+
922+
// mipdata_->lower_bound = std::min(mipdata_->upper_bound,
923+
// mipdata_->nodequeue.getBestLowerBound());
924+
925+
// bool bound_change = mipdata_->lower_bound != prev_lower_bound;
926+
// if (!submip && bound_change)
927+
// mipdata_->updatePrimalDualIntegral(
928+
// prev_lower_bound, mipdata_->lower_bound, mipdata_->upper_bound,
929+
// mipdata_->upper_bound);
930+
// mipdata_->printDisplayLine();
931+
// break;
932+
// }
933+
934+
// the search datastructure should have no installed node now
935+
assert(!worker_search.hasNode());
936+
937+
if (limit_reached) break;
938+
939+
}
940+
941+
}
942+
767943
} // while(search.hasNode())
768944
analysis_.mipTimerStop(kMipClockSearch);
769945

770946
cleanupSolve();
947+
771948
}
772949

773950
void HighsMipSolver::cleanupSolve() {

highs/mip/HighsMipWorker.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,4 +298,9 @@ double HighsMipWorker::transformNewIntegerFeasibleSolution(
298298
return -double(mipsolver_quad_objective_value + mipsolver_.model_->offset_);
299299

300300
return double(mipsolver_quad_objective_value - mipsolver_.model_->offset_);
301-
}
301+
}
302+
303+
bool HighsMipWorker::syncNodeQueue(HighsNodeQueue& nodequeue) {
304+
search_ptr_.get()->openNodesToQueue(nodequeue);
305+
return true;
306+
}

highs/mip/HighsMipWorker.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "mip/HighsLpRelaxation.h"
1515
#include "mip/HighsMipSolver.h"
1616
#include "mip/HighsMipSolverData.h"
17+
#include "mip/HighsNodeQueue.h"
1718
#include "mip/HighsPrimalHeuristics.h"
1819
#include "mip/HighsPseudocost.h"
1920
// #include "mip/HighsSeparation.h"
@@ -71,6 +72,22 @@ class HighsMipWorker {
7172
const std::vector<double>& sol,
7273
const bool possibly_store_as_new_incumbent = true);
7374

75+
bool syncSolution(double& row_violation,
76+
double& bound_violation,
77+
double& integrality_violation,
78+
std::vector<double>& solution,
79+
double& solution_objective) {
80+
row_violation = solution_.row_violation_;
81+
bound_violation = solution_.bound_violation_;
82+
integrality_violation = solution_.integrality_violation_;
83+
solution = solution_.solution_;
84+
solution_objective = solution_.solution_objective_;
85+
86+
return true;
87+
}
88+
89+
bool syncNodeQueue(HighsNodeQueue& nodequeue);
90+
7491
// todo:
7592
// timer_
7693
// sync too

0 commit comments

Comments
 (0)