Skip to content

Commit de18260

Browse files
committed
used vector of HighsMipProblemData to duplicate specific analysis
1 parent 5e1c1e9 commit de18260

File tree

5 files changed

+142
-5
lines changed

5 files changed

+142
-5
lines changed

check/TestMipSolver.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,7 @@ TEST_CASE("ines", "[highs_test_mip_solver]") {
11141114
const std::vector<double> value = {10, 20, 25, 40, 60, 70};
11151115
const std::vector<double> weight = {1, 2, 3, 6, 7, 4};
11161116
HighsLp lp;
1117+
lp.model_name_ = "ines";
11171118
lp.sense_ = ObjSense::kMaximize;
11181119
lp.num_col_ = 6;
11191120
lp.num_row_ = 2;

highs/mip/HighsMipSolver.cpp

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,9 @@ void HighsMipSolver::run() {
152152
}
153153
analysis_.mipTimerStop(kMipClockKnapsack);
154154
}
155-
// See whether the presolved problem is suitable for Ines
156-
mipdata_->mipIsInes();
155+
// If the presolved problem is not suitable for Ines, then it's
156+
// recorded as "other"
157+
if (!mipdata_->mipIsInes()) mipdata_->mipIsOther();
157158

158159
analysis_.mipTimerStart(kMipClockSolve);
159160

@@ -875,14 +876,13 @@ void HighsMipSolver::cleanupSolve(const bool mip_logging) {
875876
analysis_.mipTimerRead(kMipClockSolve),
876877
analysis_.mipTimerRead(kMipClockPostsolve));
877878
highsLogUser(options_mip_->log_options, HighsLogType::kInfo,
878-
" Max sub-MIP depth %d\n"
879879
" Nodes %llu\n"
880880
" Repair LPs %llu (%llu feasible; %llu iterations)\n"
881881
" LP iterations %llu (total)\n"
882882
" %llu (strong br.)\n"
883883
" %llu (separation)\n"
884884
" %llu (heuristics)\n",
885-
int(max_submip_level), (long long unsigned)mipdata_->num_nodes,
885+
(long long unsigned)mipdata_->num_nodes,
886886
(long long unsigned)mipdata_->total_repair_lp,
887887
(long long unsigned)mipdata_->total_repair_lp_feasible,
888888
(long long unsigned)mipdata_->total_repair_lp_iterations,
@@ -923,6 +923,68 @@ void HighsMipSolver::cleanupSolve(const bool mip_logging) {
923923
knapsack_data.sum_capacity, ines_data.num_problem,
924924
ines_data.sum_col, ines_data.sum_row);
925925

926+
const std::vector<HighsMipProblemData>& mip_problem_data = this->mipdata_->mip_problem_data_;
927+
HighsInt num_mip = static_cast<HighsInt>(mip_problem_data.size());
928+
HighsInt num_knapsack_mip = 0;
929+
size_t sum_knapsack_num_col = 0;
930+
HighsInt num_ines_mip = 0;
931+
size_t sum_ines_num_col = 0;
932+
size_t sum_ines_num_row = 0;
933+
HighsInt lc_max_submip_level = -1;
934+
HighsInt min_submip_num_col = kHighsIInf;
935+
HighsInt min_submip_num_row = kHighsIInf;
936+
for (HighsInt iMip = 0; iMip < num_mip; iMip++) {
937+
switch (mip_problem_data[iMip].type) {
938+
case HighsMipProblemType::kKnapsack:
939+
num_knapsack_mip++;
940+
sum_knapsack_num_col += mip_problem_data[iMip].num_binary;
941+
break;
942+
case HighsMipProblemType::kInes:
943+
num_ines_mip++;
944+
sum_ines_num_col += mip_problem_data[iMip].num_binary;
945+
sum_ines_num_row += mip_problem_data[iMip].num_row;
946+
break;
947+
case HighsMipProblemType::kOther:
948+
default:
949+
break;
950+
}
951+
lc_max_submip_level = std::max(mip_problem_data[iMip].submip_level, lc_max_submip_level);
952+
HighsInt submip_num_col =
953+
mip_problem_data[iMip].num_continuous +
954+
mip_problem_data[iMip].num_binary +
955+
mip_problem_data[iMip].num_general_integer +
956+
mip_problem_data[iMip].num_implied_integer;
957+
958+
min_submip_num_col = std::min(submip_num_col, min_submip_num_col);
959+
min_submip_num_row = std::min(mip_problem_data[iMip].num_row, min_submip_num_row);
960+
}
961+
highsLogUser(options_mip_->log_options, HighsLogType::kInfo,
962+
" MIPs %d (%d knapsack; %d Ines)\n",
963+
int(num_mip),
964+
int(num_knapsack_mip),
965+
int(num_ines_mip));
966+
967+
ss.str(std::string());
968+
ss << highsFormatToString(" Max sub-MIP depth %d", int(max_submip_level));
969+
if (max_submip_level > 0)
970+
ss << highsFormatToString(" min cols/rows = %d/%d\n");
971+
highsLogUser(options_mip_->log_options, HighsLogType::kInfo, "%s\n",
972+
ss.str().c_str());
973+
974+
if (num_knapsack_mip > 0 || num_ines_mip > 0)
975+
highsLogUser(options_mip_->log_options, HighsLogType::kInfo,
976+
"grep-knapsack-ines,%s,%s,%d,%" PRId64 "%d,%" PRId64 ",%" PRId64 "\n",
977+
model_->model_name_.c_str(), options_mip_->presolve.c_str(),
978+
num_knapsack_mip, sum_knapsack_num_col,
979+
num_ines_mip, sum_ines_num_col, sum_ines_num_row);
980+
981+
if (max_submip_level > 0) {
982+
}
983+
984+
985+
986+
987+
926988
if (!timeless_log) analysis_.reportMipTimer();
927989

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

highs/mip/HighsMipSolverData.cpp

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,7 @@ void HighsMipSolverData::init() {
688688
knapsack_capacity_ = 0;
689689
knapsack_integral_scale_ = 0;
690690
ines_data_.initialise();
691+
mip_problem_data_.clear();
691692

692693
if (mipsolver.options_mip_->mip_report_level == 0)
693694
dispfreq = 0;
@@ -743,7 +744,7 @@ void HighsMipSolverData::runSetup() {
743744
incumbent = postSolveStack.getReducedPrimalSolution(mipsolver.solution_);
744745
// return the objective value in the transformed space
745746
double solobj =
746-
mipsolver.solution_objective_ * (int)mipsolver.orig_model_->sense_ -
747+
mipsolver.solution_objective_ * int(mipsolver.orig_model_->sense_) -
747748
mipsolver.model_->offset_;
748749
bool feasible = mipsolver.bound_violation_ <=
749750
mipsolver.options_mip_->mip_feasibility_tolerance &&
@@ -2690,6 +2691,13 @@ bool HighsMipSolverData::mipIsKnapsack(const bool silent) {
26902691
this->knapsack_data_.num_problem++;
26912692
this->knapsack_data_.sum_variables += lp.num_col_;
26922693
this->knapsack_data_.sum_capacity += this->knapsack_capacity_;
2694+
HighsMipProblemData mip_problem_data;
2695+
mip_problem_data.clear();
2696+
mip_problem_data.submip_level = mipsolver.submip_level;
2697+
mip_problem_data.num_binary = lp.num_col_;
2698+
mip_problem_data.num_row = lp.num_row_;
2699+
mip_problem_data.type = HighsMipProblemType::kKnapsack;
2700+
this->mip_problem_data_.push_back(mip_problem_data);
26932701
}
26942702
return true;
26952703
}
@@ -2715,10 +2723,42 @@ bool HighsMipSolverData::mipIsInes(const bool silent) {
27152723
this->ines_data_.num_problem++;
27162724
this->ines_data_.sum_col += lp.num_col_;
27172725
this->ines_data_.sum_row += lp.num_row_;
2726+
HighsMipProblemData mip_problem_data;
2727+
mip_problem_data.clear();
2728+
mip_problem_data.submip_level = mipsolver.submip_level;
2729+
mip_problem_data.num_binary = lp.num_col_;
2730+
mip_problem_data.num_row = lp.num_row_;
2731+
mip_problem_data.type = HighsMipProblemType::kInes;
2732+
this->mip_problem_data_.push_back(mip_problem_data);
27182733
}
27192734
return true;
27202735
}
27212736

2737+
void HighsMipSolverData::mipIsOther() {
2738+
const HighsLp& lp = *(mipsolver.model_);
2739+
HighsMipProblemData mip_problem_data;
2740+
mip_problem_data.clear();
2741+
mip_problem_data.submip_level = mipsolver.submip_level;
2742+
for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++) {
2743+
if (lp.integrality_[iCol] == HighsVarType::kContinuous) {
2744+
mip_problem_data.num_continuous++;
2745+
} else if (lp.integrality_[iCol] == HighsVarType::kInteger) {
2746+
if (lp.col_lower_[iCol] == 0 && lp.col_upper_[iCol] == 1) {
2747+
mip_problem_data.num_binary++;
2748+
} else {
2749+
mip_problem_data.num_general_integer++;
2750+
}
2751+
} else if (lp.integrality_[iCol] == HighsVarType::kImplicitInteger) {
2752+
mip_problem_data.num_implied_integer++;
2753+
} else {
2754+
assert(111==234);
2755+
}
2756+
}
2757+
mip_problem_data.num_row = lp.num_row_;
2758+
mip_problem_data.type = HighsMipProblemType::kOther;
2759+
this->mip_problem_data_.push_back(mip_problem_data);
2760+
}
2761+
27222762
static double possInfRelDiff(const double v0, const double v1,
27232763
const double den) {
27242764
double rel_diff;
@@ -2855,6 +2895,16 @@ void HighsMipSolverData::updatePrimalDualIntegral(const double from_lower_bound,
28552895

28562896
void HighsPrimaDualIntegral::initialise() { this->value = -kHighsInf; }
28572897

2898+
void HighsMipProblemData::clear() {
2899+
this->submip_level = -1;
2900+
this->num_continuous = 0;
2901+
this->num_binary = 0;
2902+
this->num_implied_integer = 0;
2903+
this->num_general_integer = 0;
2904+
this->num_row = 0;
2905+
this->type = HighsMipProblemType::kOther;
2906+
}
2907+
28582908
void HighsKnapsackData::initialise() {
28592909
num_problem = 0;
28602910
sum_variables = 0;

highs/mip/HighsMipSolverData.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@
3030
#include "presolve/HighsSymmetry.h"
3131
#include "util/HighsTimer.h"
3232

33+
enum class HighsMipProblemType { kKnapsack = 0, kInes, kOther };
34+
35+
struct HighsMipProblemData {
36+
HighsInt submip_level;
37+
HighsInt num_continuous;
38+
HighsInt num_binary;
39+
HighsInt num_general_integer;
40+
HighsInt num_implied_integer;
41+
HighsInt num_row;
42+
HighsMipProblemType type;
43+
void clear();
44+
};
45+
3346
struct HighsKnapsackData {
3447
HighsInt num_problem;
3548
int64_t sum_variables;
@@ -175,6 +188,8 @@ struct HighsMipSolverData {
175188

176189
HighsInesData ines_data_;
177190

191+
std::vector<HighsMipProblemData> mip_problem_data_;
192+
178193
HighsMipSolverData(HighsMipSolver& mipsolver)
179194
: mipsolver(mipsolver),
180195
cutpool(mipsolver.numCol(), mipsolver.options_mip_->mip_pool_age_limit,
@@ -325,6 +340,7 @@ struct HighsMipSolverData {
325340
const userMipSolutionCallbackOrigin user_solution_callback_origin);
326341
bool mipIsKnapsack(const bool silent = false);
327342
bool mipIsInes(const bool silent = false);
343+
void mipIsOther();
328344
};
329345

330346
#endif

highs/mip/HighsPrimalHeuristics.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,15 @@ bool HighsPrimalHeuristics::solveSubMip(
152152
submipsolver.run();
153153
mipsolver.max_submip_level =
154154
std::max(submipsolver.max_submip_level + 1, mipsolver.max_submip_level);
155+
155156
mipsolver.mipdata_->knapsack_data_.add(submipsolver.mipdata_->knapsack_data_);
157+
mipsolver.mipdata_->ines_data_.add(submipsolver.mipdata_->ines_data_);
158+
159+
// Append the sub-MIP problem data to this MIP problem data
160+
mipsolver.mipdata_->mip_problem_data_.insert(mipsolver.mipdata_->mip_problem_data_.end(),
161+
submipsolver.mipdata_->mip_problem_data_.begin(),
162+
submipsolver.mipdata_->mip_problem_data_.end());
163+
156164
if (!mipsolver.submip) mipsolver.analysis_.mipTimerStop(kMipClockSubMipSolve);
157165
if (submipsolver.mipdata_) {
158166
double numUnfixed = mipsolver.mipdata_->integral_cols.size() +

0 commit comments

Comments
 (0)