Skip to content

Commit 5e1c1e9

Browse files
committed
Now tracking problems suitable for Ines
1 parent d84a6b6 commit 5e1c1e9

File tree

4 files changed

+101
-0
lines changed

4 files changed

+101
-0
lines changed

check/TestMipSolver.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,3 +1109,32 @@ TEST_CASE("knapsack", "[highs_test_mip_solver]") {
11091109

11101110
h.resetGlobalScheduler(true);
11111111
}
1112+
1113+
TEST_CASE("ines", "[highs_test_mip_solver]") {
1114+
const std::vector<double> value = {10, 20, 25, 40, 60, 70};
1115+
const std::vector<double> weight = {1, 2, 3, 6, 7, 4};
1116+
HighsLp lp;
1117+
lp.sense_ = ObjSense::kMaximize;
1118+
lp.num_col_ = 6;
1119+
lp.num_row_ = 2;
1120+
lp.col_cost_ = value;
1121+
lp.col_lower_.assign(lp.num_col_, 0);
1122+
lp.col_upper_.assign(lp.num_col_, 1);
1123+
lp.integrality_.assign(lp.num_col_, HighsVarType::kInteger);
1124+
lp.row_lower_ = {-kHighsInf, -4};
1125+
lp.row_upper_ = {6, kHighsInf};
1126+
lp.a_matrix_.format_ = MatrixFormat::kRowwise;
1127+
lp.a_matrix_.start_ = {0, 6, 12};
1128+
lp.a_matrix_.index_ = {0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5};
1129+
lp.a_matrix_.value_ = {1, -2, 3, -6, 7, 4, -6, 7, -4, -1, 2, -3};
1130+
double required_objective_value = 215;
1131+
Highs h;
1132+
// h.setOptionValue("output_flag", dev_run);
1133+
h.setOptionValue("presolve", kHighsOffString);
1134+
REQUIRE(h.passModel(lp) == HighsStatus::kOk);
1135+
REQUIRE(h.run() == HighsStatus::kOk);
1136+
if (dev_run) h.writeSolution("", 1);
1137+
REQUIRE(h.getInfo().objective_function_value == required_objective_value);
1138+
1139+
h.resetGlobalScheduler(true);
1140+
}

highs/mip/HighsMipSolver.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ void HighsMipSolver::run() {
152152
}
153153
analysis_.mipTimerStop(kMipClockKnapsack);
154154
}
155+
// See whether the presolved problem is suitable for Ines
156+
mipdata_->mipIsInes();
155157

156158
analysis_.mipTimerStart(kMipClockSolve);
157159

@@ -900,6 +902,27 @@ void HighsMipSolver::cleanupSolve(const bool mip_logging) {
900902
int((1.0 * knapsack_data.sum_capacity) / knapsack_data.num_problem));
901903
highsLogUser(options_mip_->log_options, HighsLogType::kInfo, "%s\n",
902904
ss.str().c_str());
905+
const HighsInesData& ines_data = this->mipdata_->ines_data_;
906+
ss.str(std::string());
907+
ss << highsFormatToString(" Ines MIPs %d",
908+
int(ines_data.num_problem));
909+
if (ines_data.num_problem > 0)
910+
ss << highsFormatToString(
911+
" (mean columns %d; mean rows %d)",
912+
int((1.0 * ines_data.sum_col) / ines_data.num_problem),
913+
int((1.0 * ines_data.sum_row) / ines_data.num_problem));
914+
highsLogUser(options_mip_->log_options, HighsLogType::kInfo, "%s\n",
915+
ss.str().c_str());
916+
917+
if (knapsack_data.num_problem > 0 || ines_data.num_problem > 0)
918+
highsLogUser(options_mip_->log_options, HighsLogType::kInfo,
919+
"grep-knapsack-ines,%s,%s,%d,%" PRId64 ",%" PRId64
920+
",%d,%" PRId64 ",%" PRId64 "\n",
921+
model_->model_name_.c_str(), options_mip_->presolve.c_str(),
922+
knapsack_data.num_problem, knapsack_data.sum_variables,
923+
knapsack_data.sum_capacity, ines_data.num_problem,
924+
ines_data.sum_col, ines_data.sum_row);
925+
903926
if (!timeless_log) analysis_.reportMipTimer();
904927

905928
assert(modelstatus_ != HighsModelStatus::kNotset);

highs/mip/HighsMipSolverData.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@ void HighsMipSolverData::init() {
687687
knapsack_data_.initialise();
688688
knapsack_capacity_ = 0;
689689
knapsack_integral_scale_ = 0;
690+
ines_data_.initialise();
690691

691692
if (mipsolver.options_mip_->mip_report_level == 0)
692693
dispfreq = 0;
@@ -2693,6 +2694,31 @@ bool HighsMipSolverData::mipIsKnapsack(const bool silent) {
26932694
return true;
26942695
}
26952696

2697+
bool HighsMipSolverData::mipIsInes(const bool silent) {
2698+
// Silent is to prevent duplicate logging and data collection when
2699+
// using assert(mipIsInes(true));
2700+
const HighsLp& lp = *(mipsolver.model_);
2701+
// Has to have at least one constraint
2702+
if (lp.num_row_ < 1) return false;
2703+
// Has to be a binary integer programming problem
2704+
if (!lp.isBip()) return false;
2705+
// Origin must be feasible
2706+
const double ines_feas_tol = 0;
2707+
for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++) {
2708+
if (lp.row_lower_[0] - ines_feas_tol > 0 ||
2709+
lp.row_upper_[0] + ines_feas_tol < 0)
2710+
return false;
2711+
}
2712+
if (!silent) {
2713+
highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
2714+
"MIP is an Ines problem\n");
2715+
this->ines_data_.num_problem++;
2716+
this->ines_data_.sum_col += lp.num_col_;
2717+
this->ines_data_.sum_row += lp.num_row_;
2718+
}
2719+
return true;
2720+
}
2721+
26962722
static double possInfRelDiff(const double v0, const double v1,
26972723
const double den) {
26982724
double rel_diff;
@@ -2840,3 +2866,15 @@ void HighsKnapsackData::add(const HighsKnapsackData& knapsack_data) {
28402866
this->sum_variables += knapsack_data.sum_variables;
28412867
this->sum_capacity += knapsack_data.sum_capacity;
28422868
}
2869+
2870+
void HighsInesData::initialise() {
2871+
num_problem = 0;
2872+
sum_col = 0;
2873+
sum_row = 0;
2874+
}
2875+
2876+
void HighsInesData::add(const HighsInesData& ines_data) {
2877+
this->num_problem += ines_data.num_problem;
2878+
this->sum_col += ines_data.sum_col;
2879+
this->sum_row += ines_data.sum_row;
2880+
}

highs/mip/HighsMipSolverData.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ struct HighsKnapsackData {
3838
void add(const HighsKnapsackData& knapsack_data);
3939
};
4040

41+
struct HighsInesData {
42+
HighsInt num_problem;
43+
int64_t sum_col;
44+
int64_t sum_row;
45+
void initialise();
46+
void add(const HighsInesData& ines_data);
47+
};
48+
4149
struct HighsPrimaDualIntegral {
4250
double value;
4351
double prev_lb;
@@ -165,6 +173,8 @@ struct HighsMipSolverData {
165173
HighsInt knapsack_capacity_;
166174
HighsInt knapsack_integral_scale_;
167175

176+
HighsInesData ines_data_;
177+
168178
HighsMipSolverData(HighsMipSolver& mipsolver)
169179
: mipsolver(mipsolver),
170180
cutpool(mipsolver.numCol(), mipsolver.options_mip_->mip_pool_age_limit,
@@ -314,6 +324,7 @@ struct HighsMipSolverData {
314324
const double mipsolver_objective_value,
315325
const userMipSolutionCallbackOrigin user_solution_callback_origin);
316326
bool mipIsKnapsack(const bool silent = false);
327+
bool mipIsInes(const bool silent = false);
317328
};
318329

319330
#endif

0 commit comments

Comments
 (0)