Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
e4003b5
Created structs MipRaceIncumbent and MipRaceRecord
jajhall Jul 15, 2025
e38d32c
Merge branch 'latest' into mip-race
jajhall Jul 15, 2025
a66b641
Writing incumbent solutions to shared memory
jajhall Jul 15, 2025
3f115b6
Introduced option for mip_race_concurrency, struct MipRace, last_incu…
jajhall Jul 15, 2025
d5f9db2
Added newSolution, terminate and terminated to MipRace and HighsMipSo…
jajhall Jul 17, 2025
865628c
Now to extend callbackUserSolution to generic extenalsolution method
jajhall Jul 17, 2025
ae572dc
Added mip-race unit test and restored default value of mip_race_concu…
jajhall Jul 17, 2025
9c750ec
Now to remove callback-related logic from call to queryExternalSolution
jajhall Jul 17, 2025
a4e9290
can ExternalMipSolutionQueryOrigin be moved to HighsMipSolver.h?
jajhall Jul 17, 2025
7a515c3
Now checking for terminate instruction - time to use multi-threading!
jajhall Jul 17, 2025
1bec802
Have MIP solvers running concurrently
jajhall Jul 17, 2025
41eb3f1
Failed to add HighsLogOptions to MipRace
jajhall Jul 17, 2025
239bf49
Moved MipRace struct definition to HighsMipSolver.h
jajhall Jul 18, 2025
a4f4cbc
Worker logging only to mip_worker*.log
jajhall Jul 18, 2025
0985562
Now flip terminate<->terminated
jajhall Jul 18, 2025
a3b0846
Now only terminate the MIP race if it's not already terminated
jajhall Jul 18, 2025
fcafe50
Merged latest into this branch
jajhall Jul 18, 2025
2b1a131
Introduced HighsModelStatus::kHighsInterrupt for MIP race interrupt
jajhall Jul 18, 2025
d0af6ec
Now extracting HighsMipSolverInfo
jajhall Jul 18, 2025
39456e8
WIP
jajhall Jul 18, 2025
5a5b30a
Now to start reading incumbents from other MIP solver instances
jajhall Jul 18, 2025
14e2a97
HiGHS solution has been read
jajhall Jul 19, 2025
6e65dbe
Reading HiGHS solution; different random_seed; all logging still to f…
jajhall Jul 19, 2025
54603c1
Now only reading if incumbent is newer than last read
jajhall Jul 20, 2025
ffe29d9
Prototype concurrent MIP solver
jajhall Jul 20, 2025
bf92e1c
Merge branch 'latest' into mip-race
jajhall Jul 20, 2025
f01c30c
Fixed two issues leading to CI compiler failures
jajhall Jul 20, 2025
b785eca
Need to use check/instances model in unit_tests mip-race
jajhall Jul 20, 2025
0d284c9
Introduce termination_status flag
jajhall Jul 21, 2025
ad8bca5
Introduced independent terminator status and HighsTerminator struct
jajhall Jul 21, 2025
105d560
Now unit tests pass, start using termination_status_ and HighsTerminator
jajhall Jul 21, 2025
e8a9175
Now to initialise HighsTerminator
jajhall Jul 21, 2025
e91a215
Eliminated infinite loop when HighsTermination occurs in performRestart
jajhall Jul 21, 2025
46c5bde
Stripped termination record from MipRace
jajhall Jul 21, 2025
26e930b
Now to avoid HighsTerminator call for standard MIP solve
jajhall Jul 21, 2025
9948f3c
Not so ambitious...
jajhall Jul 21, 2025
4ad6e3b
Use HighsTerminator::my_instance
jajhall Jul 21, 2025
e895296
Cleaned up; formatted
jajhall Jul 21, 2025
7058fc4
Introduced HighsMipSolver::initialiseMipRace
jajhall Jul 21, 2025
18b4356
Ready to externd terminator to sub-MIPs!
jajhall Jul 21, 2025
3487a2a
Now propagating terminator to sub-MIPs, but still have to test for it!
jajhall Jul 22, 2025
c502d1f
Flip termination conditional in HighsMipSolver::cleanupSolve() in pre…
jajhall Jul 22, 2025
6f740fe
Now termination is not performed by sub-MIPs, but they will act on a …
jajhall Jul 22, 2025
884f745
fiball now solves in 5.22 seconds
jajhall Jul 22, 2025
9b7bc10
Create gap string method
jajhall Jul 22, 2025
6570af7
Instance 0 no longer logging MIP solver solution report to console, b…
jajhall Jul 22, 2025
c52e2af
Fixed compiler warning
jajhall Jul 22, 2025
d27d46b
Cleared out development logging
jajhall Jul 22, 2025
1c5cf45
Cleaned up, and first of @mathgeekcoder's suggestions implemented
jajhall Jul 23, 2025
5a1c095
Formatted
jajhall Jul 23, 2025
a2974ce
Now reporting whole loop time for race
jajhall Jul 29, 2025
34260a4
Made @mathgeekcoder's changes, and computing the correct reduced obje…
jajhall Jul 29, 2025
6add956
Need to check for feasibility in transformed space when solution rece…
jajhall Jul 29, 2025
7d4c8be
Now checking instance solution for feasibility, and computing the cor…
jajhall Jul 30, 2025
84f4bb5
Add single presolve option to MIP race
jajhall Jul 30, 2025
6011753
Still passes bin/unit_tests mip-race
jajhall Jul 30, 2025
acd2cfc
Now able to run MIP race on single presolved model
jajhall Jul 30, 2025
6cb49c3
Formatted
jajhall Jul 30, 2025
d77e739
Removed stray printf and isolated health warning logging for MIP race
jajhall Jul 30, 2025
0c3ddc5
Deleted MIP race code
jajhall Aug 26, 2025
079dc03
Merge branch 'latest' into mip-race
jajhall Aug 26, 2025
6b4a6ee
Removed MipSolverInfo and last vestiges of MIP race
jajhall Aug 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions check/TestCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ struct MipData {
struct UserMipSolution {
double optimal_objective_value;
std::vector<double> optimal_solution;
HighsInt require_user_solution_callback_origin;
HighsInt require_external_solution_query_origin;
};

// Callback that saves message for comparison
Expand Down Expand Up @@ -193,8 +193,8 @@ HighsCallbackFunctionType userkMipUserSolution =
void* user_callback_data) {
UserMipSolution callback_data =
*(static_cast<UserMipSolution*>(user_callback_data));
if (data_out->user_solution_callback_origin ==
callback_data.require_user_solution_callback_origin) {
if (data_out->external_solution_query_origin ==
callback_data.require_external_solution_query_origin) {
if (data_out->mip_primal_bound >
callback_data.optimal_objective_value) {
// If current objective value is not optimal, pass the
Expand All @@ -203,7 +203,7 @@ HighsCallbackFunctionType userkMipUserSolution =
printf(
"userkMipUserSolution: origin = %d; %g = mip_primal_bound > "
"optimal_objective_value = %g\n",
int(data_out->user_solution_callback_origin),
int(data_out->external_solution_query_origin),
data_out->mip_primal_bound,
callback_data.optimal_objective_value);
data_in->user_has_solution = true;
Expand All @@ -218,13 +218,13 @@ HighsCallbackFunctionType userkMipUserSetSolution =
void* user_callback_data) {
const auto& callback_data =
*(static_cast<UserMipSolution*>(user_callback_data));
if (data_out->user_solution_callback_origin ==
callback_data.require_user_solution_callback_origin) {
if (data_out->external_solution_query_origin ==
callback_data.require_external_solution_query_origin) {
if (dev_run)
printf(
"userkMipUserSetSolution: origin = %d; %g = mip_primal_bound > "
"optimal_objective_value = %g\n",
int(data_out->user_solution_callback_origin),
int(data_out->external_solution_query_origin),
data_out->mip_primal_bound,
callback_data.optimal_objective_value);

Expand All @@ -239,14 +239,14 @@ HighsCallbackFunctionType userkMipUserSetPartialSolution =
void* user_callback_data) {
const auto& callback_data =
*(static_cast<UserMipSolution*>(user_callback_data));
if (data_out->user_solution_callback_origin ==
callback_data.require_user_solution_callback_origin) {
if (data_out->external_solution_query_origin ==
callback_data.require_external_solution_query_origin) {
if (dev_run)
printf(
"userkMipUserSetPartialSolution: origin = %d; %g = "
"mip_primal_bound > "
"optimal_objective_value = %g\n",
int(data_out->user_solution_callback_origin),
int(data_out->external_solution_query_origin),
data_out->mip_primal_bound,
callback_data.optimal_objective_value);

Expand Down Expand Up @@ -511,7 +511,7 @@ static void runMipUserSolutionTest(
UserMipSolution user_callback_data;
user_callback_data.optimal_objective_value = objective_function_value0;
user_callback_data.optimal_solution = optimal_solution;
user_callback_data.require_user_solution_callback_origin =
user_callback_data.require_external_solution_query_origin =
require_origin[iModel];
void* p_user_callback_data = (void*)(&user_callback_data);

Expand Down Expand Up @@ -597,4 +597,4 @@ TEST_CASE("highs-callback-mip-user-solution-c", "[highs-callback]") {

highs.run();
highs.resetGlobalScheduler(true);
}
}
34 changes: 34 additions & 0 deletions check/TestMipSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,16 @@ TEST_CASE("MIP-rowless-1", "[highs_test_mip_solver]") {
Highs highs;
if (!dev_run) highs.setOptionValue("output_flag", false);
rowlessMIP1(highs);

highs.resetGlobalScheduler(true);
}

TEST_CASE("MIP-rowless-2", "[highs_test_mip_solver]") {
Highs highs;
if (!dev_run) highs.setOptionValue("output_flag", false);
rowlessMIP2(highs);

highs.resetGlobalScheduler(true);
}

TEST_CASE("MIP-solution-limit", "[highs_test_mip_solver]") {
Expand Down Expand Up @@ -79,6 +83,8 @@ TEST_CASE("MIP-solution-limit", "[highs_test_mip_solver]") {
REQUIRE(highs.getModelStatus() == HighsModelStatus::kSolutionLimit);
highs.setOptionValue("mip_max_improving_sols", kHighsIInf);
highs.clearSolver();

highs.resetGlobalScheduler(true);
}

TEST_CASE("MIP-integrality", "[highs_test_mip_solver]") {
Expand Down Expand Up @@ -173,6 +179,8 @@ TEST_CASE("MIP-integrality", "[highs_test_mip_solver]") {
REQUIRE(info.mip_node_count == 1);
REQUIRE(fabs(info.mip_dual_bound + 6) < double_equal_tolerance);
REQUIRE(std::fabs(info.mip_gap) < 1e-12);

highs.resetGlobalScheduler(true);
}

TEST_CASE("MIP-clear-integrality", "[highs_test_mip_solver]") {
Expand Down Expand Up @@ -215,6 +223,8 @@ TEST_CASE("MIP-nmck", "[highs_test_mip_solver]") {
REQUIRE(info.num_primal_infeasibilities == 0);
REQUIRE(info.max_primal_infeasibility == 0);
REQUIRE(info.sum_primal_infeasibilities == 0);

highs.resetGlobalScheduler(true);
}

TEST_CASE("MIP-maximize", "[highs_test_mip_solver]") {
Expand Down Expand Up @@ -295,6 +305,8 @@ TEST_CASE("MIP-maximize", "[highs_test_mip_solver]") {
REQUIRE(std::abs(info.objective_function_value - info.mip_dual_bound) <=
options.mip_abs_gap);
REQUIRE(std::abs(info.mip_gap) <= options.mip_rel_gap);

highs.resetGlobalScheduler(true);
}

TEST_CASE("MIP-unbounded", "[highs_test_mip_solver]") {
Expand Down Expand Up @@ -403,6 +415,8 @@ TEST_CASE("MIP-unbounded", "[highs_test_mip_solver]") {

model_status = highs.getModelStatus();
REQUIRE(model_status == HighsModelStatus::kInfeasible);

highs.resetGlobalScheduler(true);
}

TEST_CASE("MIP-od", "[highs_test_mip_solver]") {
Expand Down Expand Up @@ -470,6 +484,8 @@ TEST_CASE("MIP-od", "[highs_test_mip_solver]") {
double_equal_tolerance);
REQUIRE(fabs(solution.col_value[0] - required_x0_value) <
double_equal_tolerance);

highs.resetGlobalScheduler(true);
}

TEST_CASE("MIP-infeasible-start", "[highs_test_mip_solver]") {
Expand Down Expand Up @@ -513,6 +529,8 @@ TEST_CASE("MIP-infeasible-start", "[highs_test_mip_solver]") {
HighsStatus::kOk);
highs.run();
REQUIRE(model_status == HighsModelStatus::kInfeasible);

highs.resetGlobalScheduler(true);
}

TEST_CASE("get-integrality", "[highs_test_mip_solver]") {}
Expand Down Expand Up @@ -556,6 +574,8 @@ TEST_CASE("MIP-bounds", "[highs_test_mip_solver]") {
obj1);
REQUIRE(obj0 == obj1);
std::remove(test_mps.c_str());

highs.resetGlobalScheduler(true);
}

TEST_CASE("MIP-get-saved-solutions", "[highs_test_mip_solver]") {
Expand Down Expand Up @@ -583,6 +603,8 @@ TEST_CASE("MIP-get-saved-solutions", "[highs_test_mip_solver]") {
REQUIRE(saved_objective_and_solution[last_saved_solution].col_value[iCol] ==
highs.getSolution().col_value[iCol]);
std::remove(solution_file.c_str());

highs.resetGlobalScheduler(true);
}

TEST_CASE("MIP-objective-target", "[highs_test_mip_solver]") {
Expand All @@ -597,6 +619,8 @@ TEST_CASE("MIP-objective-target", "[highs_test_mip_solver]") {
highs.run();
REQUIRE(highs.getModelStatus() == HighsModelStatus::kObjectiveTarget);
REQUIRE(highs.getInfo().objective_function_value > egout_optimal_objective);

highs.resetGlobalScheduler(true);
}

TEST_CASE("MIP-max-offset-test", "[highs_test_mip_solver]") {
Expand Down Expand Up @@ -625,6 +649,8 @@ TEST_CASE("MIP-max-offset-test", "[highs_test_mip_solver]") {
highs.getInfo().objective_function_value;
REQUIRE(objectiveOk(max_offset_optimal_objective, -offset_optimal_objective,
dev_run));

highs.resetGlobalScheduler(true);
}

TEST_CASE("MIP-get-saved-solutions-presolve", "[highs_test_mip_solver]") {
Expand Down Expand Up @@ -663,6 +689,8 @@ TEST_CASE("MIP-get-saved-solutions-presolve", "[highs_test_mip_solver]") {
REQUIRE(saved_objective_and_solution[last_saved_solution].col_value[iCol] ==
highs.getSolution().col_value[iCol]);
std::remove(solution_file.c_str());

highs.resetGlobalScheduler(true);
}

TEST_CASE("IP-infeasible-unbounded", "[highs_test_mip_solver]") {
Expand Down Expand Up @@ -720,6 +748,8 @@ TEST_CASE("IP-infeasible-unbounded", "[highs_test_mip_solver]") {
}
highs.setOptionValue("presolve", kHighsOnString);
}

highs.resetGlobalScheduler(true);
}

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

// Infeasible
REQUIRE(highs.getModelStatus() == HighsModelStatus::kInfeasible);

highs.resetGlobalScheduler(true);
}

bool objectiveOk(const double optimal_objective,
Expand Down Expand Up @@ -787,6 +819,8 @@ void solve(Highs& highs, std::string presolve,
require_optimal_objective, dev_run));
}
REQUIRE(highs.resetOptions() == HighsStatus::kOk);

highs.resetGlobalScheduler(true);
}

void distillationMIP(Highs& highs) {
Expand Down
3 changes: 2 additions & 1 deletion highs/highs_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,8 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) {
.value("kUnknown", HighsModelStatus::kUnknown)
.value("kSolutionLimit", HighsModelStatus::kSolutionLimit)
.value("kInterrupt", HighsModelStatus::kInterrupt)
.value("kMemoryLimit", HighsModelStatus::kMemoryLimit);
.value("kMemoryLimit", HighsModelStatus::kMemoryLimit)
.value("kHighsInterrupt", HighsModelStatus::kHighsInterrupt);
py::enum_<HighsPresolveStatus>(m, "HighsPresolveStatus", py::module_local())
.value("kNotPresolved", HighsPresolveStatus::kNotPresolved)
.value("kNotReduced", HighsPresolveStatus::kNotReduced)
Expand Down
3 changes: 2 additions & 1 deletion highs/interfaces/highs_csharp_api.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ public enum HighsModelStatus
kUnknown,
kSolutionLimit,
kInterrupt,
kMemoryLimit
kMemoryLimit,
kHighsInterrupt
}

public enum HighsIntegrality
Expand Down
1 change: 0 additions & 1 deletion highs/io/HighsIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include <iostream>

#include "lp_data/HighsCallback.h"
// #include "util/HighsInt.h"

class HighsOptions;

Expand Down
4 changes: 3 additions & 1 deletion highs/lp_data/HConst.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const double kExcessivelyLargeCostValue = 1e10;
const double kExcessivelySmallBoundValue = 1e-4;
const double kExcessivelySmallCostValue = 1e-4;

const HighsInt kNoThreadInstance = -1;
const bool kAllowDeveloperAssert = false;
const bool kExtendInvertWhenAddingRows = false;

Expand Down Expand Up @@ -218,8 +219,9 @@ enum class HighsModelStatus {
kSolutionLimit,
kInterrupt,
kMemoryLimit,
kHighsInterrupt,
kMin = kNotset,
kMax = kMemoryLimit
kMax = kHighsInterrupt
};

enum HighsCallbackType : int {
Expand Down
7 changes: 4 additions & 3 deletions highs/lp_data/Highs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4033,14 +4033,13 @@ HighsStatus Highs::callSolveMip() {
// Extract the solution
if (solver.solution_objective_ != kHighsInf) {
// There is a primal solution
HighsInt solver_solution_size = solver.solution_.size();
assert(solver_solution_size >= lp.num_col_);
//
// If the original model has semi-variables, its solution is
// (still) given by the first model_.lp_.num_col_ entries of the
// solution from the MIP solver
solution_.col_value.resize(model_.lp_.num_col_);
solution_.col_value = solver.solution_;
saved_objective_and_solution_ = solver.saved_objective_and_solution_;
this->saved_objective_and_solution_ = solver.saved_objective_and_solution_;
model_.lp_.a_matrix_.productQuad(solution_.row_value, solution_.col_value);
solution_.value_valid = true;
} else {
Expand Down Expand Up @@ -4509,6 +4508,7 @@ HighsStatus Highs::returnFromOptimizeModel(const HighsStatus run_return_status,
case HighsModelStatus::kIterationLimit:
case HighsModelStatus::kSolutionLimit:
case HighsModelStatus::kInterrupt:
case HighsModelStatus::kHighsInterrupt:
case HighsModelStatus::kUnknown:
assert(return_status == HighsStatus::kWarning);
break;
Expand Down Expand Up @@ -4549,6 +4549,7 @@ HighsStatus Highs::returnFromOptimizeModel(const HighsStatus run_return_status,
case HighsModelStatus::kIterationLimit:
case HighsModelStatus::kSolutionLimit:
case HighsModelStatus::kInterrupt:
case HighsModelStatus::kHighsInterrupt:
case HighsModelStatus::kUnknown:
// Have info and primal solution (unless infeasible). No primal solution
// in some other case, too!
Expand Down
10 changes: 5 additions & 5 deletions highs/lp_data/HighsCallback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ void HighsCallback::clearHighsCallbackOutput() {
this->data_out.cutpool_value.clear();
this->data_out.cutpool_lower.clear();
this->data_out.cutpool_upper.clear();
this->data_out.user_solution_callback_origin =
userMipSolutionCallbackOrigin::kUserMipSolutionCallbackOriginAfterSetup;
this->data_out.external_solution_query_origin =
ExternalMipSolutionQueryOrigin::kExternalMipSolutionQueryOriginAfterSetup;
}

void HighsCallback::clearHighsCallbackInput() {
Expand Down Expand Up @@ -134,8 +134,8 @@ HighsCallbackOutput::operator HighsCallbackDataOut() const {
? nullptr
: const_cast<double*>(cutpool_upper.data());

data.user_solution_callback_origin =
static_cast<HighsInt>(user_solution_callback_origin);
data.external_solution_query_origin =
static_cast<HighsInt>(external_solution_query_origin);
return data;
}

Expand Down Expand Up @@ -320,4 +320,4 @@ HighsStatus HighsCallbackInput::repairSolution() {
return HighsStatus::kError;
}
}
}
}
18 changes: 9 additions & 9 deletions highs/lp_data/HighsCallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ class Highs;
#include "lp_data/HStruct.h"
#include "lp_data/HighsCallbackStruct.h"

enum userMipSolutionCallbackOrigin {
kUserMipSolutionCallbackOriginAfterSetup = 0,
kUserMipSolutionCallbackOriginBeforeDive,
kUserMipSolutionCallbackOriginEvaluateRootNode0,
kUserMipSolutionCallbackOriginEvaluateRootNode1,
kUserMipSolutionCallbackOriginEvaluateRootNode2,
kUserMipSolutionCallbackOriginEvaluateRootNode3,
kUserMipSolutionCallbackOriginEvaluateRootNode4
enum ExternalMipSolutionQueryOrigin {
kExternalMipSolutionQueryOriginAfterSetup = 0,
kExternalMipSolutionQueryOriginBeforeDive,
kExternalMipSolutionQueryOriginEvaluateRootNode0,
kExternalMipSolutionQueryOriginEvaluateRootNode1,
kExternalMipSolutionQueryOriginEvaluateRootNode2,
kExternalMipSolutionQueryOriginEvaluateRootNode3,
kExternalMipSolutionQueryOriginEvaluateRootNode4
};

/**
Expand All @@ -54,7 +54,7 @@ struct HighsCallbackOutput {
std::vector<double> cutpool_value;
std::vector<double> cutpool_lower;
std::vector<double> cutpool_upper;
userMipSolutionCallbackOrigin user_solution_callback_origin;
ExternalMipSolutionQueryOrigin external_solution_query_origin;

operator HighsCallbackDataOut() const;
};
Expand Down
2 changes: 1 addition & 1 deletion highs/lp_data/HighsCallbackStruct.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ typedef struct {
double* cutpool_value;
double* cutpool_lower;
double* cutpool_upper;
HighsInt user_solution_callback_origin;
HighsInt external_solution_query_origin;
} HighsCallbackDataOut;

// Some external packages (e.g., jump) currently assume that the first 2 fields
Expand Down
2 changes: 2 additions & 0 deletions highs/lp_data/HighsInfoDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ HighsDebugStatus debugInfo(const HighsOptions& options, const HighsLp& lp,
case HighsModelStatus::kTimeLimit:
case HighsModelStatus::kIterationLimit:
case HighsModelStatus::kSolutionLimit:
case HighsModelStatus::kInterrupt:
case HighsModelStatus::kHighsInterrupt:
case HighsModelStatus::kUnknown:
// Should have info
assert(have_info == true);
Expand Down
1 change: 1 addition & 0 deletions highs/lp_data/HighsInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "Highs.h"
#include "lp_data/HighsLpUtils.h"
#include "lp_data/HighsModelUtils.h"
#include "mip/HighsMipSolver.h" // For getGapString
#include "model/HighsHessianUtils.h"
#include "simplex/HSimplex.h"
#include "util/HighsMatrixUtils.h"
Expand Down
Loading
Loading