Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add 1 opt #1536

Draft
wants to merge 39 commits into
base: latest
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
61618f3
Replaced hard-coded char values in MIP calls
jajhall Dec 4, 2023
80ab3b8
Added key to Src column in MIP logging
jajhall Dec 4, 2023
b352198
Renamed source to solution_source for MIP solver
jajhall Dec 4, 2023
db09887
Formatted
jajhall Dec 4, 2023
9fcecc3
Now to define methods to test column and row feasiblilty for a solution
jajhall Dec 4, 2023
bfa509f
Introduced HighsMipSolverData::solutionColFeasible and HighsMipSolver…
jajhall Dec 4, 2023
c98bb8a
Introduced HighsMipSolverData::solutionColFeasible and HighsMipSolver…
jajhall Dec 4, 2023
b00117d
Four trivial heuristics implemented for IP: little apparent value
jajhall Dec 5, 2023
c9277c5
Now understand where sub-MIPs come from and set up prototype trivial …
jajhall Dec 6, 2023
969189b
Learned that sub-MIPs can have sub-MIPS. Now to move trivial heuristi…
jajhall Dec 7, 2023
75cf894
Eliminated segfault
jajhall Dec 7, 2023
c502450
Now accounting for all trivial heuristic attempts
jajhall Dec 7, 2023
34a6674
Add submip level tracking
jajhall Dec 8, 2023
6700cfd
Renaming trivial_heuristics_data_ and copy/flushTrivialHeuristicsStat…
jajhall Dec 8, 2023
7aef9f3
Still cannot pass trivial_heuristics_statistics up and down!
jajhall Dec 8, 2023
49cc4f8
WIP
jajhall Dec 10, 2023
1ca35f3
Merge branch 'latest' into add-trivial-heuristic
jajhall Dec 10, 2023
f0ea1f9
ctest passes with trivial heuristics running
jajhall Dec 11, 2023
68072ec
Merge branch 'latest' into add-1-opt
jajhall Dec 11, 2023
d6657dd
Merged add-trivial-heuristic into this branch
jajhall Dec 11, 2023
4a727ff
Removed trivial heuristics code from this branch
jajhall Dec 11, 2023
044ffb0
Introduced HighsMipSolverData::assessIntegerFeasibleSolution as inter…
jajhall Dec 12, 2023
2e8df5e
Now ready to add first level of opt-1
jajhall Dec 12, 2023
0ed5046
Queried Leona about return value from addIncumbent, and added print s…
jajhall Dec 13, 2023
18a5a66
Reworked as line search
jajhall Dec 14, 2023
5eae6eb
bell5 now giving large changes again
jajhall Dec 15, 2023
cd1c931
Now to eliminate recursion depth for 1-opt
jajhall Dec 15, 2023
40cc9ac
Check that MIP solver isn't broken before proceeding
jajhall Dec 15, 2023
1bbfcaa
Formatted
jajhall Dec 15, 2023
a95a8a1
added return to HighsMipSolverData::solutionStatusToString
jajhall Dec 15, 2023
f1ac4df
Now handling solution_status as an enum
jajhall Dec 16, 2023
4824981
1-opt now in own method
jajhall Dec 16, 2023
e18534f
2-opt now in own method
jajhall Dec 16, 2023
1c9de68
Testing 1-opt
jajhall Dec 16, 2023
dc7ae54
Rather better attention to numerical detail
jajhall Dec 17, 2023
91a6e3e
Stop trying to move to edge of row infeasiblility
jajhall Dec 17, 2023
755896f
Stop trying to move to edge of row infeasiblility
jajhall Dec 17, 2023
bd2fc3a
Now considering candidates by decreasing |cost| in 1-opt
jajhall Dec 17, 2023
8941bc8
Merged latest into this branch
jajhall Feb 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion check/CMakeLists.txt
Expand Up @@ -163,7 +163,7 @@ set(failInstances
)

set(mipInstances
"small_mip\;3.2368421\;"
"small_mip0\;3.2368421\;"
"flugpl\;1201500\;"
"lseu\;1120|1119.9999999\;"
"egout\;(568.1007|568.1006999)\;"
Expand Down
2 changes: 1 addition & 1 deletion check/TestFilereader.cpp
Expand Up @@ -262,7 +262,7 @@ TEST_CASE("filereader-read-mps-ems-lp", "[highs_filereader]") {

TEST_CASE("filereader-integrality-constraints", "[highs_filereader]") {
std::string filename;
filename = std::string(HIGHS_DIR) + "/check/instances/small_mip.mps";
filename = std::string(HIGHS_DIR) + "/check/instances/small_mip0.mps";

// integer variables are COL03,COL04 so x[2], x[3].
const std::vector<HighsVarType> kIntegers{
Expand Down
2 changes: 1 addition & 1 deletion check/TestLpSolvers.cpp
Expand Up @@ -301,7 +301,7 @@ TEST_CASE("mip-with-lp-solver", "[highs_lp_solver]") {
Highs highs;
highs.setOptionValue("output_flag", dev_run);
std::string filename =
std::string(HIGHS_DIR) + "/check/instances/small_mip.mps";
std::string(HIGHS_DIR) + "/check/instances/small_mip0.mps";
status = highs.readModel(filename);
REQUIRE(status == HighsStatus::kOk);
highs.setOptionValue("solver", kIpmString);
Expand Down
File renamed without changes.
89 changes: 89 additions & 0 deletions check/instances/small_mip1.mps
@@ -0,0 +1,89 @@
************************************************************************
*
* The data in this file represents the following problem:
*
* Minimize Z = x1 - 2x3 + x4 + 2x5 - x8
*
* Subject to:
*
* 2.5 <= 3x1 + x2 - 2x4 - x5 - x8
* 2x2 + 1.1x3 <= 2.1
* x3 + x6 = 4.0
* 1.8 <= 2.8x4 -1.2x7 <= 5.0
* 3.0 <= 5.6x1 + x5 + 1.9x8 <= 15.0
*
* where:
*
* 2.5 <= x1
* 0 <= x2 <= 4.1
* 0 <= x3
* 0 <= x4
* 0.5 <= x5 <= 4.0
* 0 <= x6
* 0 <= x7
* 0 <= x8 <= 4.3
*
* x3, x4 are 0,1 variables.
*
*************************************************************************
*
*N=8, M=5, NZ= 14
*-----cost-----
* 1.0 0.0 -2.0 1.0 2.0 0.0 0.0 -1.0
*------A------
* 3.0 1.0 -2.0 -1.0 -1.0
* 2.0 1.1
* 1.0 1.0
* 2.8 -1.2
* 5.6 1.0 1.9
*------LB------
* 2.5 -inf 4.0 1.8 3.0
*------UB------
* inf 2.1 4.0 5.0 15.0
*
*
*************************************************************************
NAME EXAMPLE
ROWS
N OBJ
G ROW01
L ROW02
E ROW03
G ROW04
L ROW05
COLUMNS
COL01 OBJ 1.0
COL01 ROW01 3.0 ROW05 5.6
COL02 ROW01 1.0 ROW02 2.0
*
* Mark COL03 and COL04 as integer variables.
*
INT1 'MARKER' 'INTORG'
COL03 OBJ -2.0
COL03 ROW02 1.1 ROW03 1.0
COL04 OBJ 1.0
COL04 ROW01 -2.0 ROW04 2.8
INT1END 'MARKER' 'INTEND'
*
COL05 OBJ 2.0
COL05 ROW01 -1.0 ROW05 1.0
COL06 ROW03 1.0
COL07 ROW04 -1.2
COL08 OBJ -1.0
COL08 ROW01 -1.0 ROW05 1.9
RHS
RHS1 ROW01 2.5
RHS1 ROW02 2.1
RHS1 ROW03 4.0
RHS1 ROW04 1.8
RHS1 ROW05 15.0
RANGES
RNG1 ROW04 3.2
RNG1 ROW05 12.0
BOUNDS
LO BND1 COL01 2.5
UP BND1 COL02 4.1
LO BND1 COL05 0.5
UP BND1 COL05 4.0
UP BND1 COL08 4.3
ENDATA
21 changes: 21 additions & 0 deletions src/lp_data/HighsOptions.h
Expand Up @@ -401,6 +401,9 @@ struct HighsOptionsStruct {
double mip_rel_gap;
double mip_abs_gap;
double mip_heuristic_effort;
std::string mip_trivial_heuristics;
HighsInt mip_opt_1_heuristic;
HighsInt mip_opt_2_heuristic;
double mip_min_logging_interval;
#ifdef HIGHS_DEBUGSOL
std::string mip_debug_solution_file;
Expand Down Expand Up @@ -872,6 +875,24 @@ class HighsOptions : public HighsOptionsStruct {
&mip_heuristic_effort, 0.0, 0.05, 1.0);
records.push_back(record_double);

record_string = new OptionRecordString(
"mip_trivial_heuristics",
"MIP trivial heuristics option: \"off\", \"choose\" or \"on\"",
advanced, &mip_trivial_heuristics, kHighsChooseString);
records.push_back(record_string);

record_int = new OptionRecordInt(
"mip_opt_1_heuristic",
"MIP 1-opt heuristic option: 0 => off, 1 => on, 2 => aggressive",
advanced, &mip_opt_1_heuristic, 0, 1, 2);
records.push_back(record_int);

record_int = new OptionRecordInt(
"mip_opt_2_heuristic",
"MIP 2-opt heuristic option: 0 => off, 1 => on, 2 => aggressive",
advanced, &mip_opt_2_heuristic, 0, 0, 2);
records.push_back(record_int);

record_double = new OptionRecordDouble(
"mip_rel_gap",
"Tolerance on relative gap, |ub-lb|/|ub|, to determine whether "
Expand Down
6 changes: 4 additions & 2 deletions src/mip/HighsLpRelaxation.cpp
Expand Up @@ -1073,7 +1073,8 @@ HighsLpRelaxation::Status HighsLpRelaxation::run(bool resolve_on_error) {
if (info.basis_validity == kBasisValidityInvalid) return Status::kError;

if (info.primal_solution_status == kSolutionStatusFeasible)
mipsolver.mipdata_->trySolution(lpsolver.getSolution().col_value, 'T');
mipsolver.mipdata_->trySolution(lpsolver.getSolution().col_value,
kSolutionSourceUnbounded);

return Status::kUnbounded;
case HighsModelStatus::kUnknown:
Expand Down Expand Up @@ -1278,7 +1279,8 @@ HighsLpRelaxation::Status HighsLpRelaxation::resolveLp(HighsDomain* domain) {
for (HighsInt i = 0; i != mipsolver.numCol(); ++i)
objsum += roundsol[i] * mipsolver.colCost(i);

mipsolver.mipdata_->addIncumbent(roundsol, double(objsum), 'S');
mipsolver.mipdata_->assessIntegerFeasibleSolution(
roundsol, double(objsum), kSolutionSourceSolveLp);
objsum = 0;
}

Expand Down
13 changes: 8 additions & 5 deletions src/mip/HighsMipSolver.cpp
Expand Up @@ -31,17 +31,21 @@ using std::fabs;

HighsMipSolver::HighsMipSolver(HighsCallback& callback,
const HighsOptions& options, const HighsLp& lp,
const HighsSolution& solution, bool submip)
const HighsSolution& solution, bool submip,
HighsInt submip_level)
: callback_(&callback),
options_mip_(&options),
model_(&lp),
orig_model_(&lp),
solution_objective_(kHighsInf),
submip(submip),
submip_level(submip_level),
rootbasis(nullptr),
pscostinit(nullptr),
clqtableinit(nullptr),
implicinit(nullptr) {
assert(!submip || submip_level > 0);
max_submip_level = 0;
if (solution.value_valid) {
// MIP solver doesn't check row residuals, but they should be OK
// so validate using assert
Expand Down Expand Up @@ -127,7 +131,7 @@ void HighsMipSolver::run() {
if (modelstatus_ == HighsModelStatus::kOptimal) {
mipdata_->lower_bound = 0;
mipdata_->upper_bound = 0;
mipdata_->transformNewIntegerFeasibleSolution(std::vector<double>());
mipdata_->transformAndPossiblyStoreSolution(std::vector<double>());
}
cleanupSolve();
return;
Expand Down Expand Up @@ -610,20 +614,19 @@ void HighsMipSolver::cleanupSolve() {
" %.2f (presolve)\n"
" %.2f (postsolve)\n"
" Nodes %llu\n"
" Max sub-MIP depth %d\n"
" LP iterations %llu (total)\n"
" %llu (strong br.)\n"
" %llu (separation)\n"
" %llu (heuristics)\n",
timer_.read(timer_.solve_clock),
timer_.read(timer_.presolve_clock),
timer_.read(timer_.postsolve_clock),
(long long unsigned)mipdata_->num_nodes,
(long long unsigned)mipdata_->num_nodes, int(max_submip_level),
(long long unsigned)mipdata_->total_lp_iterations,
(long long unsigned)mipdata_->sb_lp_iterations,
(long long unsigned)mipdata_->sepa_lp_iterations,
(long long unsigned)mipdata_->heuristic_lp_iterations);

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

void HighsMipSolver::runPresolve(const HighsInt presolve_reduction_limit) {
Expand Down
4 changes: 3 additions & 1 deletion src/mip/HighsMipSolver.h
Expand Up @@ -45,6 +45,8 @@ class HighsMipSolver {
std::vector<HighsObjectiveSolution> saved_objective_and_solution_;

bool submip;
HighsInt submip_level;
HighsInt max_submip_level;
const HighsBasis* rootbasis;
const HighsPseudocostInitialization* pscostinit;
const HighsCliqueTable* clqtableinit;
Expand Down Expand Up @@ -82,7 +84,7 @@ class HighsMipSolver {

HighsMipSolver(HighsCallback& callback, const HighsOptions& options,
const HighsLp& lp, const HighsSolution& solution,
bool submip = false);
bool submip = false, HighsInt submip_level = 0);

~HighsMipSolver();

Expand Down