Skip to content

Commit

Permalink
Merge branch 'latest' into fix-1724
Browse files Browse the repository at this point in the history
  • Loading branch information
jajhall committed May 7, 2024
2 parents 7d14659 + 0bd3176 commit 053a624
Show file tree
Hide file tree
Showing 28 changed files with 497 additions and 106 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/build-meson.yml
Expand Up @@ -7,12 +7,15 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest] # windows-latest takes to long
# macos-latest issue with micromamba action
# windows-latest takes to long
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v4
with:
submodules: "recursive"
fetch-depth: 0

- name: Install Conda environment
uses: mamba-org/setup-micromamba@v1
with:
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/build-python-package.yml
Expand Up @@ -34,17 +34,17 @@ jobs:

- name: Build sdist
run: |
python3 -m pip install build
python3 -m pip install build --break-system-packages
python3 -m build --sdist
- name: Install sdist
run: |
ls dist
python3 -m pip install dist/*.tar.gz
python3 -m pip install dist/*.tar.gz --break-system-packages
- name: Test highspy
run: |
python3 -m pip install pytest
python3 -m pip install pytest --break-system-packages
python3 -m pytest $GITHUB_WORKSPACE
build_sdist_win:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/check-python-package.yml
Expand Up @@ -26,7 +26,7 @@ jobs:

- name: Build sdist
run: |
python3 -m pip install build setuptools twine
python3 -m pip install build setuptools twine --break-system-packages
python3 -m build --sdist
python3 -m build --wheel
twine check dist/*
Expand Down
5 changes: 3 additions & 2 deletions CMakeLists.txt
Expand Up @@ -384,8 +384,9 @@ else()
endif()
message(STATUS "Git hash: " ${GITHASH})

string(TIMESTAMP TODAY "%Y-%m-%d")
message(STATUS "Compilation date: " ${TODAY})
# Deprecate
# string(TIMESTAMP TODAY "%Y-%m-%d")
# message(STATUS "Compilation date: " ${TODAY})

configure_file(${HIGHS_SOURCE_DIR}/src/HConfig.h.in ${HIGHS_BINARY_DIR}/HConfig.h)

Expand Down
12 changes: 12 additions & 0 deletions FEATURES.md
Expand Up @@ -18,4 +18,16 @@ Added version info to executable

Inserting `pdlp_iteration_count` into various structs (for v1.7.0) breaks the C API, so it has been moved to the end of those structs

setBasis has been added to highspy

writePresolvedModel has been added

Saved MIP solution pool is populated when presolve reduces MIP to empty

Compilation date has been removed improve build reproducibility. Methods to print compilation dates are deprecated

Logging and error return when user-supplied solution or basis is rejected on vector dimensions




25 changes: 0 additions & 25 deletions HiGHS.sln

This file was deleted.

8 changes: 8 additions & 0 deletions app/CMakeLists.txt
Expand Up @@ -29,6 +29,14 @@ if(FAST_BUILD)

target_link_libraries(highs-bin highs)

if(APPLE)
set_target_properties(highs-bin PROPERTIES INSTALL_RPATH
"@loader_path/../${CMAKE_INSTALL_LIBDIR};@loader_path")
elseif (UNIX)
set_target_properties(highs-bin PROPERTIES INSTALL_RPATH
"$ORIGIN:$ORIGIN/../${CMAKE_INSTALL_LIBDIR}")
endif()

# install the binary
install(TARGETS highs-bin EXPORT highs-targets
RUNTIME)
Expand Down
21 changes: 20 additions & 1 deletion check/CMakeLists.txt
Expand Up @@ -170,6 +170,20 @@ if (NOT FAST_BUILD OR ALL_TESTS)
"standgub\;68\; 1.2576995000\;"
"standmps\;218\; 1.4060175000\;"
)

set(successMacArmInstances
"25fv47\;3103\; 5.5018458883\;"
"80bau3b\;3705\; 9.8722419241\;"
"adlittle\;74\; 2.2549496316\;"
"afiro\;22\;-4.6475314286\;"
"etamacro\;531\;-7.5571523330\;"
"greenbea\;5156\;-7.2555248130\;"
"shell\;623\; 1.2088253460\;"
"stair\;531\;-2.5126695119\;"
"standata\;72\; 1.2576995000\;"
"standgub\;68\; 1.2576995000\;"
"standmps\;218\; 1.4060175000\;"
)

set(infeasibleInstances
"bgetam\; infeasible"
Expand Down Expand Up @@ -270,7 +284,12 @@ if (NOT FAST_BUILD OR ALL_TESTS)
endmacro(add_instancetests)

# add tests for success and fail instances
add_instancetests(successInstances "Optimal")
if (APPLE AND (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm64"))
add_instancetests(successMacArmInstances "Optimal")
else()
add_instancetests(successInstances "Optimal")
endif()

add_instancetests(failInstances "Fail")
add_instancetests(infeasibleInstances "Infeasible")
#add_instancetests(unboundedInstances "Unbounded")
Expand Down
24 changes: 23 additions & 1 deletion check/TestBasis.cpp
Expand Up @@ -111,7 +111,7 @@ TEST_CASE("set-pathological-basis", "[highs_basis_data]") {
// Set up a basis with everything nonbasic. This will lead to
// basic_index being empty when passed to
// HFactor::setupGeneral. Previously this led to the creation of
// pointer &basic_index[0] that caused Windows faiure referenced in
// pointer &basic_index[0] that caused Windows failure referenced in
// #1129, and reported in #1166. However, now that
// basic_index.data() is used to create the pointer, there is no
// Windows failure. Within HFactor::setupGeneral and
Expand Down Expand Up @@ -156,6 +156,28 @@ TEST_CASE("Basis-no-basic", "[highs_basis_data]") {
REQUIRE(highs.getModelStatus() == HighsModelStatus::kOptimal);
}

TEST_CASE("Basis-singular", "[highs_basis_data]") {
Highs highs;
highs.setOptionValue("output_flag", dev_run);
HighsLp lp;
lp.num_col_ = 2;
lp.num_row_ = 2;
lp.col_cost_ = {1, 1};
lp.col_lower_ = {0, 0};
lp.col_upper_ = {1, 1};
lp.row_lower_ = {1, 1};
lp.row_upper_ = {2, 2};
lp.a_matrix_.start_ = {0, 2, 4};
lp.a_matrix_.index_ = {0, 1, 0, 1};
lp.a_matrix_.value_ = {1, 2, 2, 4};
highs.passModel(lp);
HighsBasis basis;
REQUIRE(highs.setBasis(basis) == HighsStatus::kError);
basis.col_status = {HighsBasisStatus::kBasic, HighsBasisStatus::kBasic};
basis.row_status = {HighsBasisStatus::kLower, HighsBasisStatus::kLower};
REQUIRE(highs.setBasis(basis) == HighsStatus::kOk);
}

// No commas in test case name.
void testBasisReloadModel(Highs& highs, const bool from_file) {
// Checks that no simplex iterations are required if a saved optimal
Expand Down
176 changes: 158 additions & 18 deletions check/TestCAPI.c
Expand Up @@ -12,6 +12,74 @@
const HighsInt dev_run = 0;
const double double_equal_tolerance = 1e-5;

void checkGetCallbackDataOutPointer(const HighsCallbackDataOut* data_out, const char* name, HighsInt valid) {
const void* name_p = Highs_getCallbackDataOutItem(data_out, name);
if (valid) {
if (!name_p) printf("checkGetCallbackDataOutItem fail for %s (valid = %d)\n", name, (int)valid);
assert(name_p);
} else {
if (name_p) printf("checkGetCallbackDataOutItem fail for %s (valid = %d)\n",
name, (int)valid);
assert(!name_p);
}
}

void checkGetCallbackDataOutHighsInt(const HighsCallbackDataOut* data_out, const char* name, HighsInt value) {
const void* name_p = Highs_getCallbackDataOutItem(data_out, name);
if (!name_p) {
printf("checkGetCallbackDataOutItem fail for %s\n", name);
assert(name_p);
} else {
HighsInt check_value = *(HighsInt*)(name_p);
HighsInt value_ok = check_value == value;
if (!value_ok) printf("checkGetCallbackDataOutItem fail for %s (%d = check_value != value = %d)\n",
name, (int)check_value, (int)value);
assert(value_ok);
}
}

void checkGetCallbackDataOutInt(const HighsCallbackDataOut* data_out, const char* name, int value) {
const void* name_p = Highs_getCallbackDataOutItem(data_out, name);
if (!name_p) {
printf("checkGetCallbackDataOutInt fail for %s\n", name);
assert(name_p);
} else {
int check_value = *(int*)(name_p);
int value_ok = check_value == value;
if (!value_ok) printf("checkGetCallbackDataOutInt fail for %s (%d = check_value != value = %d)\n",
name, check_value, value);
assert(value_ok);
}
}

void checkGetCallbackDataOutInt64(const HighsCallbackDataOut* data_out, const char* name, int64_t value) {
const void* name_p = Highs_getCallbackDataOutItem(data_out, name);
if (!name_p) {
printf("checkGetCallbackDataOutInt64 fail for %s\n", name);
assert(name_p);
} else {
int64_t check_value = *(int*)(name_p);
int value_ok = check_value == value;
if (!value_ok) printf("checkGetCallbackDataOutInt64 fail for %s (%d = check_value != value = %d)\n",
name, (int)check_value, (int)value);
assert(value_ok);
}
}

void checkGetCallbackDataOutDouble(const HighsCallbackDataOut* data_out, const char* name, double value) {
const void* name_p = Highs_getCallbackDataOutItem(data_out, name);
if (!name_p) {
printf("checkGetCallbackDataOutDouble fail for %s\n", name);
assert(name_p);
} else {
double check_value = *(double*)(name_p);
double value_ok = check_value == value;
if (!value_ok) printf("checkGetCallbackDataOutDouble fail for %s (%g = check_value != value = %g)\n",
name, check_value, value);
assert(value_ok);
}
}

static void userCallback(const int callback_type, const char* message,
const HighsCallbackDataOut* data_out,
HighsCallbackDataIn* data_in,
Expand All @@ -22,7 +90,78 @@ static void userCallback(const int callback_type, const char* message,
if (callback_type == kHighsCallbackLogging) {
if (dev_run) printf("userCallback(%11.4g): %s\n", local_callback_data, message);
} else if (callback_type == kHighsCallbackMipImprovingSolution) {
if (dev_run) printf("userCallback(%11.4g): improving solution with objective = %g\n", local_callback_data, data_out->objective_function_value);
// Test the accessor function for data_out
//
// Check that passing an valid name returns a non-null pointer,
// and that the corresponding value is the same as obtained using
// the struct
const void* objective_function_value_p =
Highs_getCallbackDataOutItem(data_out, kHighsCallbackDataOutObjectiveFunctionValueName);
assert(objective_function_value_p);
double objective_function_value = *(double*)(objective_function_value_p);
assert(objective_function_value == data_out->objective_function_value);
if (dev_run) printf("userCallback(%11.4g): improving solution with objective = %g\n",
local_callback_data, objective_function_value);
// Now test all more simply
checkGetCallbackDataOutInt(data_out,
kHighsCallbackDataOutLogTypeName, -1);
checkGetCallbackDataOutDouble(data_out,
kHighsCallbackDataOutRunningTimeName,
data_out->running_time);
checkGetCallbackDataOutHighsInt(data_out,
kHighsCallbackDataOutSimplexIterationCountName,
data_out->simplex_iteration_count);
checkGetCallbackDataOutHighsInt(data_out,
kHighsCallbackDataOutIpmIterationCountName,
data_out->ipm_iteration_count);
checkGetCallbackDataOutHighsInt(data_out,
kHighsCallbackDataOutPdlpIterationCountName,
data_out->pdlp_iteration_count);
checkGetCallbackDataOutDouble(data_out,
kHighsCallbackDataOutObjectiveFunctionValueName,
data_out->objective_function_value);
checkGetCallbackDataOutInt64(data_out,
kHighsCallbackDataOutMipNodeCountName,
data_out->mip_node_count);
checkGetCallbackDataOutDouble(data_out,
kHighsCallbackDataOutMipPrimalBoundName,
data_out->mip_primal_bound);
checkGetCallbackDataOutDouble(data_out,
kHighsCallbackDataOutMipDualBoundName,
data_out->mip_dual_bound);
checkGetCallbackDataOutDouble(data_out,
kHighsCallbackDataOutMipGapName,
data_out->mip_gap);
// Cutpool data structure is not assigned, so num_col, num_cut and
// num_nz are unassigned
// checkGetCallbackDataOutHighsInt(data_out,
// kHighsCallbackDataOutCutpoolNumColName, 0);
// checkGetCallbackDataOutHighsInt(data_out,
// kHighsCallbackDataOutCutpoolNumCutName, 0);
// checkGetCallbackDataOutHighsInt(data_out,
// kHighsCallbackDataOutCutpoolNumNzName, 0);

// Check that passing an unrecognised name returns NULL
const void* foo_p = Highs_getCallbackDataOutItem(data_out, "foo");
assert(!foo_p);
// Check that passing the name of an assigned vector returns
// non-NULL, and that the corresponding value is the same as
// obtained using the struct
const void* mip_solution_void_p =
Highs_getCallbackDataOutItem(data_out,
kHighsCallbackDataOutMipSolutionName);
assert(mip_solution_void_p);
double mip_solution0 = *(double*)(mip_solution_void_p);
assert(mip_solution0 == *(data_out->mip_solution));
if (dev_run) printf("userCallback(%11.4g): improving solution with value[0] = %g\n",
local_callback_data, mip_solution0);
// Cutpool data structure is not assigned, so cannot check that
// passing names of the unassigned vectors returns NULL
// assert(!Highs_getCallbackDataOutItem(data_out, kHighsCallbackDataOutCutpoolStartName));
// assert(!Highs_getCallbackDataOutItem(data_out, kHighsCallbackDataOutCutpoolIndexName));
// assert(!Highs_getCallbackDataOutItem(data_out, kHighsCallbackDataOutCutpoolValueName));
// assert(!Highs_getCallbackDataOutItem(data_out, kHighsCallbackDataOutCutpoolLowerName));
// assert(!Highs_getCallbackDataOutItem(data_out, kHighsCallbackDataOutCutpoolUpperName));
} else if (callback_type == kHighsCallbackMipLogging) {
if (dev_run) printf("userCallback(%11.4g): MIP logging\n", local_callback_data);
data_in->user_interrupt = 1;
Expand Down Expand Up @@ -71,7 +210,8 @@ void version_api() {
printf("HiGHS version minor %"HIGHSINT_FORMAT"\n", Highs_versionMinor());
printf("HiGHS version patch %"HIGHSINT_FORMAT"\n", Highs_versionPatch());
printf("HiGHS githash: %s\n", Highs_githash());
printf("HiGHS compilation date %s\n", Highs_compilationDate());
// Compilation date is deprecated.
// printf("HiGHS compilation date %s\n", Highs_compilationDate());
}
}

Expand Down Expand Up @@ -1618,22 +1758,22 @@ void test_setSolution() {
}
*/
int main() {
minimal_api_illegal_lp();
test_callback();
version_api();
full_api();
minimal_api_lp();
minimal_api_mip();
minimal_api_qp();
full_api_options();
full_api_lp();
full_api_mip();
full_api_qp();
pass_presolve_get_lp();
options();
test_getColsByRange();
test_passHessian();
test_ranging();
minimal_api_illegal_lp();
test_callback();
version_api();
full_api();
minimal_api_lp();
minimal_api_mip();
minimal_api_qp();
full_api_options();
full_api_lp();
full_api_mip();
full_api_qp();
pass_presolve_get_lp();
options();
test_getColsByRange();
test_passHessian();
test_ranging();
test_getModel();
// test_setSolution();
return 0;
Expand Down

0 comments on commit 053a624

Please sign in to comment.