Skip to content

Commit 14dcc67

Browse files
committed
Merged hpm into this branch and resolved minor conflicts
2 parents aa54dbd + d59635c commit 14dcc67

File tree

9 files changed

+132
-41
lines changed

9 files changed

+132
-41
lines changed

CMakeLists.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -808,9 +808,6 @@ else(FAST_BUILD)
808808
if(BUILD_CXX)
809809
add_subdirectory(app)
810810
add_subdirectory(examples)
811-
if (HIPO)
812-
add_subdirectory(highs/ipm/hipo)
813-
endif()
814811
endif()
815812

816813
if(BUILD_TESTING)

check/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ if ((NOT FAST_BUILD OR ALL_TESTS) AND NOT (BUILD_EXTRA_UNIT_ONLY))
4848
TestHighsRbTree.cpp
4949
TestHighsSparseMatrix.cpp
5050
TestHighsVersion.cpp
51+
TestHipo.cpp
5152
TestHSet.cpp
5253
TestICrash.cpp
5354
TestIis.cpp

check/TestHipo.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include "HCheckConfig.h"
2+
#include "Highs.h"
3+
#include "catch.hpp"
4+
#include "io/Filereader.h"
5+
#include "ipm/hipo/ipm/Solver.h"
6+
#include "ipm/hipo/ipm/Status.h"
7+
#include "lp_data/HighsCallback.h"
8+
#include "parallel/HighsParallel.h"
9+
10+
// Example for using HiPO from its C++ interface. The program solves the Netlib
11+
// problem afiro.
12+
13+
#include <unistd.h>
14+
15+
#include <cmath>
16+
#include <iostream>
17+
#include <vector>
18+
19+
const bool dev_run = false;
20+
21+
TEST_CASE("test-hipo-afiro", "[highs_hipo]") {
22+
// Test that hipo runs and finds correct solution for afiro
23+
24+
std::string model = "afiro.mps";
25+
const double expected_obj = -464.753;
26+
27+
Highs highs;
28+
highs.setOptionValue("output_flag", dev_run);
29+
highs.setOptionValue("solver", kHipoString);
30+
highs.setOptionValue("timeless_log", kHighsOnString);
31+
32+
std::string filename = std::string(HIGHS_DIR) + "/check/instances/" + model;
33+
highs.readModel(filename);
34+
35+
HighsStatus status = highs.run();
36+
REQUIRE(status == HighsStatus::kOk);
37+
38+
const double actual_obj = highs.getObjectiveValue();
39+
REQUIRE(std::abs(actual_obj - expected_obj) < 0.001);
40+
41+
highs.resetGlobalScheduler(true);
42+
}
43+
44+
TEST_CASE("test-hipo-deterministic", "[highs_hipo]") {
45+
// Test that hipo finds the exact same solution if run twice
46+
47+
std::string model = "80bau3b.mps";
48+
49+
Highs highs;
50+
highs.setOptionValue("output_flag", dev_run);
51+
highs.setOptionValue(kSolverString, kHipoString);
52+
highs.setOptionValue(kParallelString, kHighsOnString);
53+
highs.setOptionValue(kRunCrossoverString, kHighsOffString);
54+
55+
std::string filename = std::string(HIGHS_DIR) + "/check/instances/" + model;
56+
highs.readModel(filename);
57+
58+
HighsStatus status = highs.run();
59+
REQUIRE(status == HighsStatus::kOk);
60+
61+
const HighsSolution solution_1 = highs.getSolution();
62+
63+
highs.run();
64+
const HighsSolution solution_2 = highs.getSolution();
65+
66+
REQUIRE(solution_1.value_valid == solution_2.value_valid);
67+
REQUIRE(solution_1.dual_valid == solution_2.dual_valid);
68+
REQUIRE(solution_1.col_value == solution_2.col_value);
69+
REQUIRE(solution_1.row_value == solution_2.row_value);
70+
REQUIRE(solution_1.col_dual == solution_2.col_dual);
71+
REQUIRE(solution_1.row_dual == solution_2.row_dual);
72+
73+
highs.resetGlobalScheduler(true);
74+
}

cmake/FindHipoDeps.cmake

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,24 @@ option(BLAS_ROOT "Root directory of BLAS or OpenBLAS" "")
33
message(STATUS "BLAS_ROOT is " ${BLAS_ROOT})
44

55
if(NOT APPLE)
6-
find_library(BLAS_LIB
7-
NAMES blas HINTS
8-
"${BLAS_ROOT}/lib")
6+
find_library(OPENBLAS_LIB
7+
NAMES openblas
8+
HINTS "${BLAS_ROOT}/lib")
99

10-
if(BLAS_LIB)
11-
message("Found BLAS library at ${BLAS_LIB}")
12-
else(BLAS_LIB)
13-
find_library(OPENBLAS_LIB
14-
NAMES openblas
15-
HINTS "${BLAS_ROOT}/lib")
16-
if(NOT OPENBLAS_LIB)
17-
message(FATAL_ERROR "No BLAS library found")
18-
endif(NOT OPENBLAS_LIB)
10+
if(OPENBLAS_LIB)
1911
message("Found OpenBLAS library at ${OPENBLAS_LIB}")
20-
endif(BLAS_LIB)
21-
12+
13+
else(OPENBLAS_LIB)
14+
find_library(BLAS_LIB
15+
NAMES blas HINTS
16+
"${BLAS_ROOT}/lib")
17+
18+
if(NOT BLAS_LIB)
19+
message(FATAL_ERROR "No BLAS library found")
20+
endif(NOT BLAS_LIB)
21+
message("Found BLAS library at ${BLAS_LIB}")
22+
endif(OPENBLAS_LIB)
23+
2224
endif(NOT APPLE)
2325

2426
# METIS

highs/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,13 @@ else()
188188

189189
if(APPLE)
190190
target_link_libraries(highs "-framework Accelerate")
191-
target_compile_definitions(highs PRIVATE FRAMEWORK_ACCELERATE)
191+
target_compile_definitions(highs PRIVATE HIPO_USES_APPLE_BLAS)
192192
else(APPLE)
193193
if(BLAS_LIB)
194194
target_link_libraries(highs "${BLAS_LIB}")
195195
elseif(OPENBLAS_LIB)
196196
target_link_libraries(highs "${OPENBLAS_LIB}")
197+
target_compile_definitions(highs PRIVATE HIPO_USES_OPENBLAS)
197198
else()
198199
message(FATAL_ERROR "No BLAS library available")
199200
endif(BLAS_LIB)

highs/ipm/IpxWrapper.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,13 @@ HighsStatus solveLpHipo(HighsLpSolverObject& solver_object) {
402402
solver_object.highs_info_, solver_object.callback_);
403403
}
404404

405+
#ifdef HIPO_USES_OPENBLAS
406+
// function to set number of threads of openblas
407+
extern "C" {
408+
void openblas_set_num_threads(int num_threads);
409+
}
410+
#endif
411+
405412
HighsStatus solveLpHipo(const HighsOptions& options, HighsTimer& timer,
406413
const HighsLp& lp, HighsBasis& highs_basis,
407414
HighsSolution& highs_solution,
@@ -439,6 +446,11 @@ HighsStatus solveLpHipo(const HighsOptions& options, HighsTimer& timer,
439446
// Indicate that no imprecise solution has (yet) been found
440447
resetModelStatusAndHighsInfo(model_status, highs_info);
441448

449+
#ifdef HIPO_USES_OPENBLAS
450+
// force openblas to run in serial, for determinism and better performance
451+
openblas_set_num_threads(1);
452+
#endif
453+
442454
// Create solver instance
443455
hipo::Solver hipo{};
444456

@@ -499,13 +511,22 @@ HighsStatus solveLpHipo(const HighsOptions& options, HighsTimer& timer,
499511
hipo_options.parallel = hipo::kOptionParallelChoose;
500512
}
501513

502-
// Highs does not have an option to select NE/AS approach.
503-
// For now use choose, but an option should be added for the user to choose.
504-
hipo_options.nla = hipo::kOptionNlaChoose;
514+
// Parse hipo_system option
515+
if (options.hipo_system == kHipoAugmentedString) {
516+
hipo_options.nla = hipo::kOptionNlaAugmented;
517+
} else if (options.hipo_system == kHipoNormalEqString) {
518+
hipo_options.nla = hipo::kOptionNlaNormEq;
519+
} else if (options.hipo_system == kHighsChooseString) {
520+
hipo_options.nla = hipo::kOptionNlaChoose;
521+
} else {
522+
highsLogUser(options.log_options, HighsLogType::kError,
523+
"Unknown value of option hipo_system\n");
524+
model_status = HighsModelStatus::kSolveError;
525+
return HighsStatus::kError;
526+
}
505527

506528
// ===========================================================================
507529
// TO DO
508-
// - add options for NE/AS
509530
// - consider adding options for parallel tree/node
510531
// - block size for dense factorisation can have large impact on performance
511532
// and depends on the specific architecture. It may be worth exposing it to

highs/ipm/hipo/CMakeLists.txt

Lines changed: 0 additions & 18 deletions
This file was deleted.

highs/ipm/hipo/ipm/FactorHiGHSSolver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ void FactorHiGHSSolver::setParallel(Options& options) {
588588
log_stream << "Full requested\n";
589589
break;
590590
case kOptionParallelChoose: {
591-
#ifdef FRAMEWORK_ACCELERATE
591+
#ifdef HIPO_USES_APPLE_BLAS
592592
// Blas on Apple do not work well with parallel_node, but parallel_tree
593593
// seems to always be beneficial.
594594
parallel_node = false;

highs/lp_data/HighsOptions.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,11 @@ const string kReadSolutionFileString = "read_solution_file";
293293
// String for HiGHS log file option
294294
const string kLogFileString = "log_file";
295295

296+
// Strings for HiPO system option
297+
const string kHipoSystemString = "hipo_system";
298+
const string kHipoAugmentedString = "augmented";
299+
const string kHipoNormalEqString = "normaleq";
300+
296301
// Strings for MIP LP/IPM options
297302
const string kMipLpSolverString = "mip_lp_solver";
298303
const string kMipIpmSolverString = "mip_ipm_solver";
@@ -359,6 +364,7 @@ struct HighsOptionsStruct {
359364
// Options for IPM solver
360365
double ipm_optimality_tolerance;
361366
HighsInt ipm_iteration_limit;
367+
std::string hipo_system;
362368

363369
// Options for PDLP solver
364370
bool pdlp_scaling;
@@ -527,6 +533,7 @@ struct HighsOptionsStruct {
527533
timeless_log(false),
528534
ipm_optimality_tolerance(0.0),
529535
ipm_iteration_limit(0),
536+
hipo_system(""),
530537
pdlp_scaling(false),
531538
pdlp_iteration_limit(0),
532539
pdlp_e_restart_method(0),
@@ -1243,6 +1250,12 @@ class HighsOptions : public HighsOptionsStruct {
12431250
&ipm_iteration_limit, 0, kHighsIInf, kHighsIInf);
12441251
records.push_back(record_int);
12451252

1253+
record_string = new OptionRecordString(
1254+
kHipoSystemString,
1255+
"HiPO Newton system option: \"augmented\", \"normaleq\" or \"choose\".",
1256+
advanced, &hipo_system, kHighsChooseString);
1257+
records.push_back(record_string);
1258+
12461259
record_bool = new OptionRecordBool(
12471260
"pdlp_scaling", "Scaling option for PDLP solver: Default = true",
12481261
advanced, &pdlp_scaling, true);

0 commit comments

Comments
 (0)