Skip to content

Commit 773a215

Browse files
committed
Testing Ines, and now calling FJ after trivial heuristics and FJ
1 parent f394409 commit 773a215

File tree

9 files changed

+318
-51
lines changed

9 files changed

+318
-51
lines changed

highs/lp_data/HighsOptions.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,7 @@ struct HighsOptionsStruct {
439439
double mip_rel_gap;
440440
double mip_abs_gap;
441441
double mip_heuristic_effort;
442+
bool mip_heuristic_run_ines;
442443
bool mip_heuristic_run_feasibility_jump;
443444
bool mip_heuristic_run_rins;
444445
bool mip_heuristic_run_rens;
@@ -590,6 +591,7 @@ struct HighsOptionsStruct {
590591
mip_rel_gap(0.0),
591592
mip_abs_gap(0.0),
592593
mip_heuristic_effort(0.0),
594+
mip_heuristic_run_ines(false),
593595
mip_heuristic_run_feasibility_jump(false),
594596
mip_heuristic_run_rins(false),
595597
mip_heuristic_run_rens(false),
@@ -1136,6 +1138,11 @@ class HighsOptions : public HighsOptionsStruct {
11361138
&mip_heuristic_effort, 0.0, 0.05, 1.0);
11371139
records.push_back(record_double);
11381140

1141+
record_bool =
1142+
new OptionRecordBool("mip_heuristic_run_ines", "Use Ines' heuristic",
1143+
advanced, &mip_heuristic_run_ines, true);
1144+
records.push_back(record_bool);
1145+
11391146
record_bool =
11401147
new OptionRecordBool("mip_heuristic_run_feasibility_jump",
11411148
"Use the feasibility jump heuristic", advanced,

highs/mip/HighsFeasibilityJump.cpp

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "util/HighsSparseMatrix.h"
1111

1212
HighsModelStatus HighsMipSolverData::feasibilityJump() {
13+
this->feasibility_jump_time_ = -mipsolver.timer_.read();
1314
// This is the (presolved) model being solved
1415
const HighsLp* model = this->mipsolver.model_;
1516
const HighsLogOptions& log_options = mipsolver.options_mip_->log_options;
@@ -35,6 +36,9 @@ HighsModelStatus HighsMipSolverData::feasibilityJump() {
3536
/* equalityTolerance = */ epsilon,
3637
/* violationTolerance = */ feastol);
3738

39+
bool have_solution = this->mipsolver.solution_.size() > 0;
40+
if (have_solution) col_value = this->mipsolver.solution_;
41+
3842
for (HighsInt col = 0; col < model->num_col_; ++col) {
3943
double lower = model->col_lower_[col];
4044
double upper = model->col_upper_[col];
@@ -66,13 +70,23 @@ HighsModelStatus HighsMipSolverData::feasibilityJump() {
6670
solver.addVar(fjVarType, lower, upper,
6771
sense_multiplier * model->col_cost_[col]);
6872

69-
double initial_assignment = 0.0;
70-
if (std::isfinite(lower)) {
71-
initial_assignment = lower;
72-
} else if (std::isfinite(upper)) {
73-
initial_assignment = upper;
73+
if (have_solution) {
74+
if (col_value[col] < lower || col_value[col] > upper) {
75+
highsLogUser(log_options, HighsLogType::kError,
76+
"HighsMipSolverData::feasibilityJump() incumbent solution "
77+
"for column %d is %g, not in [%g, %g]\n",
78+
int(col), col_value[col], lower, upper);
79+
return HighsModelStatus::kSolveError;
80+
}
81+
} else {
82+
double initial_assignment = 0.0;
83+
if (std::isfinite(lower)) {
84+
initial_assignment = lower;
85+
} else if (std::isfinite(upper)) {
86+
initial_assignment = upper;
87+
}
88+
col_value[col] = initial_assignment;
7489
}
75-
col_value[col] = initial_assignment;
7690
}
7791

7892
HighsSparseMatrix a_matrix;
@@ -129,6 +143,8 @@ HighsModelStatus HighsMipSolverData::feasibilityJump() {
129143
// use trySolution rather than addIncumbent for an explicit check.
130144
trySolution(col_value, kSolutionSourceFeasibilityJump);
131145
}
146+
this->feasibility_jump_time_ += mipsolver.timer_.read();
147+
this->feasibility_jump_objective_ = objective_function_value;
132148
return HighsModelStatus::kNotset;
133149
#endif
134150
}

highs/mip/HighsMipSolver.cpp

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,31 @@ void HighsMipSolver::run() {
183183
mipdata_->callbackUserSolution(solution_objective_,
184184
kUserMipSolutionCallbackOriginAfterSetup);
185185

186-
const bool mip_heuristic_run_ines = false;
186+
// Apply the trivial heuristics
187+
analysis_.mipTimerStart(kMipClockTrivialHeuristics);
188+
HighsModelStatus returned_model_status = mipdata_->trivialHeuristics();
189+
analysis_.mipTimerStop(kMipClockTrivialHeuristics);
190+
if (modelstatus_ == HighsModelStatus::kNotset &&
191+
returned_model_status == HighsModelStatus::kInfeasible) {
192+
// trivialHeuristics can spot trivial infeasibility, so act on it
193+
modelstatus_ = returned_model_status;
194+
cleanupSolve();
195+
return;
196+
}
197+
198+
// Don't report on this MIP type, or re-record the MIP
187199
const bool ines_silent = true;
188200
if (mipdata_->mipIsInes(ines_silent)) {
189-
if (mip_heuristic_run_ines) {
201+
assert(mipdata_->mipIsInesLookup());
202+
if (options_mip_->mip_heuristic_run_ines) {
203+
analysis_.mipTimerStart(kMipClockInes);
190204
HighsStatus ines_status = mipdata_->heuristics.mipHeuristicInes();
205+
analysis_.mipTimerStop(kMipClockInes);
206+
if (ines_status == HighsStatus::kError) {
207+
modelstatus_ = HighsModelStatus::kSolveError;
208+
cleanupSolve();
209+
return;
210+
}
191211
}
192212
}
193213

@@ -203,25 +223,27 @@ void HighsMipSolver::run() {
203223
cleanupSolve();
204224
return;
205225
}
206-
const bool bailout_after_feasibility_jump = false;
207-
if (bailout_after_feasibility_jump) {
208-
highsLogUser(options_mip_->log_options, HighsLogType::kInfo,
209-
"HighsMipSolver: Bailing out after Feasibility Jump with "
210-
"model status = %s\n",
211-
utilModelStatusToString(returned_model_status).c_str());
212-
modelstatus_ = HighsModelStatus::kInterrupt;
226+
if (returned_model_status == HighsModelStatus::kSolveError) {
227+
modelstatus_ = returned_model_status;
213228
cleanupSolve();
214229
return;
215230
}
216231
}
217-
// Apply the trivial heuristics
218-
analysis_.mipTimerStart(kMipClockTrivialHeuristics);
219-
HighsModelStatus returned_model_status = mipdata_->trivialHeuristics();
220-
analysis_.mipTimerStop(kMipClockTrivialHeuristics);
221-
if (modelstatus_ == HighsModelStatus::kNotset &&
222-
returned_model_status == HighsModelStatus::kInfeasible) {
223-
// trivialHeuristics can spot trivial infeasibility, so act on it
224-
modelstatus_ = returned_model_status;
232+
if (!submip && mipdata_->mipIsInesLookup()) {
233+
printf("grepInesFJ,%s,%d,%d,%g,%d,%g,%g,%g,%g\n",
234+
model_->model_name_.c_str(), int(model_->num_col_),
235+
int(model_->num_row_), model_->offset_,
236+
mipdata_->ines_zero_solution_, mipdata_->ines_objective_,
237+
mipdata_->ines_time_, mipdata_->feasibility_jump_objective_,
238+
mipdata_->feasibility_jump_time_);
239+
}
240+
const bool bailout_after_feasibility_jump = false;
241+
if (bailout_after_feasibility_jump) {
242+
highsLogUser(options_mip_->log_options, HighsLogType::kInfo,
243+
"HighsMipSolver: Bailing out after Feasibility Jump with "
244+
"model status = %s\n",
245+
utilModelStatusToString(returned_model_status).c_str());
246+
modelstatus_ = HighsModelStatus::kInterrupt;
225247
cleanupSolve();
226248
return;
227249
}

highs/mip/HighsMipSolverData.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ std::string HighsMipSolverData::solutionSourceToString(
8181
} else if (solution_source == kSolutionSourceUserSolution) {
8282
if (code) return "X";
8383
return "User solution";
84+
} else if (solution_source == kSolutionSourceInes) {
85+
if (code) return "i";
86+
return "Ines";
8487
} else if (solution_source == kSolutionSourceCleanup) {
8588
if (code) return " ";
8689
return "";
@@ -687,6 +690,11 @@ void HighsMipSolverData::init() {
687690
knapsack_capacity_ = 0;
688691
knapsack_integral_scale_ = 0;
689692
mip_problem_data_.clear();
693+
ines_time_ = 0;
694+
ines_objective_ = 0;
695+
ines_zero_solution_ = false;
696+
feasibility_jump_time_ = 0;
697+
feasibility_jump_objective_ = 0;
690698

691699
if (mipsolver.options_mip_->mip_report_level == 0)
692700
dispfreq = 0;
@@ -2730,6 +2738,13 @@ bool HighsMipSolverData::mipIsInes(const bool silent) {
27302738
return true;
27312739
}
27322740

2741+
bool HighsMipSolverData::mipIsInesLookup() const {
2742+
HighsInt num_mip = static_cast<HighsInt>(mip_problem_data_.record.size());
2743+
if (num_mip == 0) return false;
2744+
return mip_problem_data_.record[num_mip - 1].type ==
2745+
HighsMipProblemType::kInes;
2746+
}
2747+
27332748
void HighsMipSolverData::mipIsOther() {
27342749
const HighsLp& lp = *(mipsolver.model_);
27352750
HighsMipProblemRecord mip_problem_record;

highs/mip/HighsMipSolverData.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ enum MipSolutionSource : int {
8585
kSolutionSourceTrivialL,
8686
kSolutionSourceTrivialU,
8787
kSolutionSourceTrivialP,
88+
kSolutionSourceInes,
8889
kSolutionSourceCleanup,
8990
kSolutionSourceCount
9091
};
@@ -181,6 +182,11 @@ struct HighsMipSolverData {
181182
HighsInt knapsack_integral_scale_;
182183

183184
HighsMipProblemData mip_problem_data_;
185+
double ines_time_;
186+
double ines_objective_;
187+
bool ines_zero_solution_;
188+
double feasibility_jump_time_;
189+
double feasibility_jump_objective_;
184190

185191
HighsMipSolverData(HighsMipSolver& mipsolver)
186192
: mipsolver(mipsolver),
@@ -331,6 +337,7 @@ struct HighsMipSolverData {
331337
const double mipsolver_objective_value,
332338
const userMipSolutionCallbackOrigin user_solution_callback_origin);
333339
bool mipIsKnapsack(const bool silent = false);
340+
bool mipIsInesLookup() const;
334341
bool mipIsInes(const bool silent = false);
335342
void mipIsOther();
336343
};

0 commit comments

Comments
 (0)