Skip to content

Commit 26e930b

Browse files
committed
Now to avoid HighsTerminator call for standard MIP solve
1 parent 46c5bde commit 26e930b

File tree

6 files changed

+102
-49
lines changed

6 files changed

+102
-49
lines changed

check/TestMipSolver.cpp

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,16 @@ TEST_CASE("MIP-rowless-1", "[highs_test_mip_solver]") {
4040
Highs highs;
4141
if (!dev_run) highs.setOptionValue("output_flag", false);
4242
rowlessMIP1(highs);
43+
44+
highs.resetGlobalScheduler(true);
4345
}
4446

4547
TEST_CASE("MIP-rowless-2", "[highs_test_mip_solver]") {
4648
Highs highs;
4749
if (!dev_run) highs.setOptionValue("output_flag", false);
4850
rowlessMIP2(highs);
51+
52+
highs.resetGlobalScheduler(true);
4953
}
5054

5155
TEST_CASE("MIP-solution-limit", "[highs_test_mip_solver]") {
@@ -79,6 +83,8 @@ TEST_CASE("MIP-solution-limit", "[highs_test_mip_solver]") {
7983
REQUIRE(highs.getModelStatus() == HighsModelStatus::kSolutionLimit);
8084
highs.setOptionValue("mip_max_improving_sols", kHighsIInf);
8185
highs.clearSolver();
86+
87+
highs.resetGlobalScheduler(true);
8288
}
8389

8490
TEST_CASE("MIP-integrality", "[highs_test_mip_solver]") {
@@ -173,6 +179,8 @@ TEST_CASE("MIP-integrality", "[highs_test_mip_solver]") {
173179
REQUIRE(info.mip_node_count == 1);
174180
REQUIRE(fabs(info.mip_dual_bound + 6) < double_equal_tolerance);
175181
REQUIRE(std::fabs(info.mip_gap) < 1e-12);
182+
183+
highs.resetGlobalScheduler(true);
176184
}
177185

178186
TEST_CASE("MIP-clear-integrality", "[highs_test_mip_solver]") {
@@ -215,6 +223,8 @@ TEST_CASE("MIP-nmck", "[highs_test_mip_solver]") {
215223
REQUIRE(info.num_primal_infeasibilities == 0);
216224
REQUIRE(info.max_primal_infeasibility == 0);
217225
REQUIRE(info.sum_primal_infeasibilities == 0);
226+
227+
highs.resetGlobalScheduler(true);
218228
}
219229

220230
TEST_CASE("MIP-maximize", "[highs_test_mip_solver]") {
@@ -295,6 +305,8 @@ TEST_CASE("MIP-maximize", "[highs_test_mip_solver]") {
295305
REQUIRE(std::abs(info.objective_function_value - info.mip_dual_bound) <=
296306
options.mip_abs_gap);
297307
REQUIRE(std::abs(info.mip_gap) <= options.mip_rel_gap);
308+
309+
highs.resetGlobalScheduler(true);
298310
}
299311

300312
TEST_CASE("MIP-unbounded", "[highs_test_mip_solver]") {
@@ -403,6 +415,8 @@ TEST_CASE("MIP-unbounded", "[highs_test_mip_solver]") {
403415

404416
model_status = highs.getModelStatus();
405417
REQUIRE(model_status == HighsModelStatus::kInfeasible);
418+
419+
highs.resetGlobalScheduler(true);
406420
}
407421

408422
TEST_CASE("MIP-od", "[highs_test_mip_solver]") {
@@ -470,6 +484,8 @@ TEST_CASE("MIP-od", "[highs_test_mip_solver]") {
470484
double_equal_tolerance);
471485
REQUIRE(fabs(solution.col_value[0] - required_x0_value) <
472486
double_equal_tolerance);
487+
488+
highs.resetGlobalScheduler(true);
473489
}
474490

475491
TEST_CASE("MIP-infeasible-start", "[highs_test_mip_solver]") {
@@ -513,6 +529,8 @@ TEST_CASE("MIP-infeasible-start", "[highs_test_mip_solver]") {
513529
HighsStatus::kOk);
514530
highs.run();
515531
REQUIRE(model_status == HighsModelStatus::kInfeasible);
532+
533+
highs.resetGlobalScheduler(true);
516534
}
517535

518536
TEST_CASE("get-integrality", "[highs_test_mip_solver]") {}
@@ -556,6 +574,8 @@ TEST_CASE("MIP-bounds", "[highs_test_mip_solver]") {
556574
obj1);
557575
REQUIRE(obj0 == obj1);
558576
std::remove(test_mps.c_str());
577+
578+
highs.resetGlobalScheduler(true);
559579
}
560580

561581
TEST_CASE("MIP-get-saved-solutions", "[highs_test_mip_solver]") {
@@ -583,6 +603,8 @@ TEST_CASE("MIP-get-saved-solutions", "[highs_test_mip_solver]") {
583603
REQUIRE(saved_objective_and_solution[last_saved_solution].col_value[iCol] ==
584604
highs.getSolution().col_value[iCol]);
585605
std::remove(solution_file.c_str());
606+
607+
highs.resetGlobalScheduler(true);
586608
}
587609

588610
TEST_CASE("MIP-objective-target", "[highs_test_mip_solver]") {
@@ -597,6 +619,8 @@ TEST_CASE("MIP-objective-target", "[highs_test_mip_solver]") {
597619
highs.run();
598620
REQUIRE(highs.getModelStatus() == HighsModelStatus::kObjectiveTarget);
599621
REQUIRE(highs.getInfo().objective_function_value > egout_optimal_objective);
622+
623+
highs.resetGlobalScheduler(true);
600624
}
601625

602626
TEST_CASE("MIP-max-offset-test", "[highs_test_mip_solver]") {
@@ -625,6 +649,8 @@ TEST_CASE("MIP-max-offset-test", "[highs_test_mip_solver]") {
625649
highs.getInfo().objective_function_value;
626650
REQUIRE(objectiveOk(max_offset_optimal_objective, -offset_optimal_objective,
627651
dev_run));
652+
653+
highs.resetGlobalScheduler(true);
628654
}
629655

630656
TEST_CASE("MIP-get-saved-solutions-presolve", "[highs_test_mip_solver]") {
@@ -663,6 +689,8 @@ TEST_CASE("MIP-get-saved-solutions-presolve", "[highs_test_mip_solver]") {
663689
REQUIRE(saved_objective_and_solution[last_saved_solution].col_value[iCol] ==
664690
highs.getSolution().col_value[iCol]);
665691
std::remove(solution_file.c_str());
692+
693+
highs.resetGlobalScheduler(true);
666694
}
667695

668696
TEST_CASE("IP-infeasible-unbounded", "[highs_test_mip_solver]") {
@@ -720,6 +748,8 @@ TEST_CASE("IP-infeasible-unbounded", "[highs_test_mip_solver]") {
720748
}
721749
highs.setOptionValue("presolve", kHighsOnString);
722750
}
751+
752+
highs.resetGlobalScheduler(true);
723753
}
724754

725755
TEST_CASE("IP-with-fract-bounds-no-presolve", "[highs_test_mip_solver]") {
@@ -755,6 +785,8 @@ TEST_CASE("IP-with-fract-bounds-no-presolve", "[highs_test_mip_solver]") {
755785

756786
// Infeasible
757787
REQUIRE(highs.getModelStatus() == HighsModelStatus::kInfeasible);
788+
789+
highs.resetGlobalScheduler(true);
758790
}
759791

760792
bool objectiveOk(const double optimal_objective,
@@ -787,6 +819,8 @@ void solve(Highs& highs, std::string presolve,
787819
require_optimal_objective, dev_run));
788820
}
789821
REQUIRE(highs.resetOptions() == HighsStatus::kOk);
822+
823+
highs.resetGlobalScheduler(true);
790824
}
791825

792826
void distillationMIP(Highs& highs) {
@@ -1003,17 +1037,24 @@ TEST_CASE("issue-2432", "[highs_test_mip_solver]") {
10031037
}
10041038

10051039
TEST_CASE("mip-race", "[highs_test_mip_solver]") {
1006-
const bool ci_test = true;//false;//
1007-
const std::string model = ci_test ? "rgn" : "fiball";
1040+
const bool ci_test = true; // false;//
1041+
const std::string model = ci_test ? "flugpl" : "fiball";
10081042
// "neos-3381206-awhea";
1009-
const std::string model_file = ci_test ?
1010-
std::string(HIGHS_DIR) + "/check/instances/" + model + ".mps" :
1011-
"/srv/miplib2017/" + model + ".mps.gz";
1043+
const std::string model_file =
1044+
ci_test ? std::string(HIGHS_DIR) + "/check/instances/" + model + ".mps"
1045+
: "/srv/miplib2017/" + model + ".mps.gz";
10121046
Highs h;
1013-
// if (ci_test) h.setOptionValue("output_flag", dev_run);
1014-
const HighsInt mip_race_concurrency = ci_test ? 4 : 4;
1047+
if (ci_test) h.setOptionValue("output_flag", dev_run);
1048+
const HighsInt mip_race_concurrency = ci_test ? 2 : 4;
10151049
h.setOptionValue("mip_race_concurrency", mip_race_concurrency);
10161050
// h.setOptionValue("mip_race_read_solutions", false);
10171051
REQUIRE(h.readModel(model_file) == HighsStatus::kOk);
10181052
REQUIRE(h.run() == HighsStatus::kOk);
1053+
1054+
if (ci_test) {
1055+
h.clearSolver();
1056+
h.setOptionValue("mip_race_read_solutions", false);
1057+
REQUIRE(h.run() == HighsStatus::kOk);
1058+
}
1059+
h.resetGlobalScheduler(true);
10191060
}

highs/lp_data/Highs.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4080,10 +4080,11 @@ HighsStatus Highs::callSolveMip() {
40804080
solver.mip_race_.initialise(mip_race_concurrency, instance,
40814081
&mip_race_record,
40824082
options_.log_options);
4083-
solver.initialiseTerminator(mip_race_concurrency, instance, terminator_record.data());
4084-
double this_time = timer_.read();
4085-
highsLogUser(options_.log_options, HighsLogType::kInfo,
4086-
"instance0: call run() %f6.4\n", this_time);
4083+
solver.initialiseTerminator(mip_race_concurrency, instance,
4084+
terminator_record.data());
4085+
double this_time = timer_.read();
4086+
highsLogUser(options_.log_options, HighsLogType::kInfo,
4087+
"instance0: call run() %f6.4\n", this_time);
40874088
mip_time[instance] = -this_time;
40884089
solver.run();
40894090
mip_time[instance] += timer_.read();
@@ -4094,10 +4095,12 @@ HighsStatus Highs::callSolveMip() {
40944095
worker.mip_race_.initialise(mip_race_concurrency, instance,
40954096
&mip_race_record,
40964097
worker_options[instance].log_options);
4097-
worker.initialiseTerminator(mip_race_concurrency, instance, terminator_record.data());
4098-
double this_time = timer_.read();
4099-
highsLogUser(options_.log_options, HighsLogType::kInfo,
4100-
"instance%d: call run() %f6.4\n", int(instance), this_time);
4098+
worker.initialiseTerminator(mip_race_concurrency, instance,
4099+
terminator_record.data());
4100+
double this_time = timer_.read();
4101+
highsLogUser(options_.log_options, HighsLogType::kInfo,
4102+
"instance%d: call run() %f6.4\n", int(instance),
4103+
this_time);
41014104
mip_time[instance] = -this_time;
41024105
worker.run();
41034106
mip_time[instance] += timer_.read();

highs/mip/HighsMipSolver.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ HighsMipSolver::~HighsMipSolver() = default;
7070
void HighsMipSolver::run() {
7171
modelstatus_ = HighsModelStatus::kNotset;
7272

73-
if (!submip) highsLogUser(options_mip_->log_options, HighsLogType::kInfo,
74-
"instance%d: top run() %6.4f (MIP)\n", int(this->mip_race_.my_instance), this->timer_.read());
73+
if (!submip)
74+
highsLogUser(options_mip_->log_options, HighsLogType::kInfo,
75+
"instance%d: top run() %6.4f (MIP)\n",
76+
int(this->mip_race_.my_instance), this->timer_.read());
7577

7678
if (submip) {
7779
analysis_.analyse_mip_time = false;
@@ -688,16 +690,20 @@ void HighsMipSolver::run() {
688690

689691
void HighsMipSolver::cleanupSolve() {
690692
if (!submip) {
691-
if (terminator_.notTerminatedNw()) {
693+
if (terminator_.notTerminated()) {
692694
// No other instance has terminated the MIP race, so terminate
693695
// it
694696
highsLogUser(options_mip_->log_options, HighsLogType::kInfo,
695-
"instance%d: terminate %6.4f (MIP)\n", int(this->mipdata_->mipRaceMyInstance()), this->timer_.read());
696-
terminator_.terminateNw();
697+
"instance%d: terminate %6.4f (MIP)\n",
698+
int(this->mipdata_->mipRaceMyInstance()),
699+
this->timer_.read());
700+
terminator_.terminate();
697701
} else {
698702
// Indicate that this MIP race instance has been interrupted
699703
highsLogUser(options_mip_->log_options, HighsLogType::kInfo,
700-
"instance%d: terminated %6.4f (MIP)\n", int(this->mipdata_->mipRaceMyInstance()), this->timer_.read());
704+
"instance%d: terminated %6.4f (MIP)\n",
705+
int(this->mipdata_->mipRaceMyInstance()),
706+
this->timer_.read());
701707
modelstatus_ = HighsModelStatus::kHighsInterrupt;
702708
}
703709
mipdata_->mipRaceReport();
@@ -987,14 +993,14 @@ bool HighsMipSolver::solutionFeasible(const HighsLp* lp,
987993
}
988994

989995
void HighsMipSolver::initialiseTerminator(HighsInt num_instance_,
990-
HighsInt my_instance_,
991-
HighsModelStatus* record_) {
996+
HighsInt my_instance_,
997+
HighsModelStatus* record_) {
992998
this->termination_status_ = HighsModelStatus::kNotset;
993999
this->terminator_.initialise(num_instance_, my_instance_, record_);
9941000
}
9951001

996-
std::vector<HighsModelStatus> HighsMipSolver::initialiseRecord(HighsInt num_instance) const {
1002+
std::vector<HighsModelStatus> HighsMipSolver::initialiseRecord(
1003+
HighsInt num_instance) const {
9971004
std::vector<HighsModelStatus> record(num_instance, HighsModelStatus::kNotset);
9981005
return record;
9991006
}
1000-

highs/mip/HighsMipSolver.h

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,14 @@ struct HighsTerminator {
6464
HighsInt my_instance;
6565
HighsModelStatus* record;
6666
void clear();
67-
void initialise(HighsInt num_instance_,
68-
HighsInt my_instance_,
69-
HighsModelStatus*record_);
70-
void terminateNw();
71-
HighsModelStatus terminatedNw() const;
72-
bool notTerminatedNw() const;
67+
void initialise(HighsInt num_instance_, HighsInt my_instance_,
68+
HighsModelStatus* record_);
69+
void terminate();
70+
HighsModelStatus terminated() const;
71+
bool notTerminated() const;
7372
void report(const HighsLogOptions log_options) const;
7473
};
75-
74+
7675
class HighsMipSolver {
7776
public:
7877
HighsCallback* callback_;
@@ -168,10 +167,14 @@ class HighsMipSolver {
168167
double& integrality_violation, HighsCDouble& obj) const;
169168
std::vector<HighsModelStatus> initialiseRecord(HighsInt num_instance) const;
170169
void initialiseTerminator(HighsInt num_instance_ = 0,
171-
HighsInt my_instance_ = kNoThreadInstance,
172-
HighsModelStatus* record_ = nullptr);
173-
bool terminate() const { return this->termination_status_ != HighsModelStatus::kNotset; }
174-
HighsModelStatus terminationStatus() const { return this->termination_status_; }
170+
HighsInt my_instance_ = kNoThreadInstance,
171+
HighsModelStatus* record_ = nullptr);
172+
bool terminate() const {
173+
return this->termination_status_ != HighsModelStatus::kNotset;
174+
}
175+
HighsModelStatus terminationStatus() const {
176+
return this->termination_status_;
177+
}
175178
};
176179

177180
#endif

highs/mip/HighsMipSolverData.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2422,14 +2422,14 @@ bool HighsMipSolverData::checkLimits(int64_t nodeOffset) const {
24222422
if (!mipsolver.submip) {
24232423
highsLogUser(options.log_options, HighsLogType::kInfo,
24242424
"instance%d: terminated? %6.4f (MIP)\n", int(this->mipRaceMyInstance()), this->mipsolver.timer_.read());
2425-
assert(this->terminatedNw() == this->terminatedNw());
2426-
if (this->terminatedNw()) {
2425+
assert(this->terminated() == this->terminated());
2426+
if (this->terminated()) {
24272427
highsLogUser(options.log_options, HighsLogType::kInfo,
24282428
"instance%d: terminated %6.4f (MIP)\n", int(this->mipRaceMyInstance()), this->mipsolver.timer_.read());
24292429
return true;
24302430
}
2431-
assert(this->terminatedNw() == this->terminatedNw());
2432-
if (this->terminatedNw()) return true;
2431+
assert(this->terminated() == this->terminated());
2432+
if (this->terminated()) return true;
24332433
}
24342434

24352435
// Possible user interrupt
@@ -2734,14 +2734,14 @@ void HighsMipSolverData::mipRaceReport() const {
27342734
if (mipsolver.mip_race_.record) mipsolver.mip_race_.report();
27352735
}
27362736

2737-
void HighsMipSolverData::terminateNw() {
2737+
void HighsMipSolverData::terminate() {
27382738
if (mipsolver.terminator_.num_instance <= 0) return;
2739-
mipsolver.terminator_.terminateNw();
2739+
mipsolver.terminator_.terminate();
27402740
}
27412741

2742-
bool HighsMipSolverData::terminatedNw() const {
2742+
bool HighsMipSolverData::terminated() const {
27432743
if (mipsolver.terminator_.num_instance > 0)
2744-
mipsolver.termination_status_ = mipsolver.terminator_.terminatedNw();
2744+
mipsolver.termination_status_ = mipsolver.terminator_.terminated();
27452745
return mipsolver.termination_status_ != HighsModelStatus::kNotset;
27462746
}
27472747

@@ -3033,13 +3033,13 @@ void HighsTerminator::initialise(HighsInt num_instance_,
30333033
this->record = record_;
30343034
}
30353035

3036-
void HighsTerminator::terminateNw() {
3036+
void HighsTerminator::terminate() {
30373037
assert(this->record);
30383038
assert(this->my_instance < this->num_instance);
30393039
this->record[this->my_instance] = HighsModelStatus::kHighsInterrupt;
30403040
}
30413041

3042-
HighsModelStatus HighsTerminator::terminatedNw() const {
3042+
HighsModelStatus HighsTerminator::terminated() const {
30433043
assert(this->record);
30443044
for (HighsInt instance = 0; instance < this->num_instance; instance++) {
30453045
if (this->record[instance] != HighsModelStatus::kNotset)
@@ -3048,7 +3048,7 @@ HighsModelStatus HighsTerminator::terminatedNw() const {
30483048
return HighsModelStatus::kNotset;
30493049
}
30503050

3051-
bool HighsTerminator::notTerminatedNw() const {
3051+
bool HighsTerminator::notTerminated() const {
30523052
assert(this->record);
30533053
for (HighsInt instance = 0; instance < this->num_instance; instance++) {
30543054
if (this->record[instance] != HighsModelStatus::kNotset)

highs/mip/HighsMipSolverData.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,8 @@ struct HighsMipSolverData {
308308
std::vector<double>& solution);
309309
void mipRaceReport() const;
310310

311-
void terminateNw();
312-
bool terminatedNw() const;
311+
void terminate();
312+
bool terminated() const;
313313
};
314314

315315
#endif

0 commit comments

Comments
 (0)