Skip to content

Commit ddcf4ac

Browse files
authored
Merge pull request ERGO-Code#2346 from ERGO-Code/fix-2251
Introduced relative KKT error data to `HighsInfo`, and using it to assess optimality claims from PDLP and IPM without crossover
2 parents d8ff906 + 718829d commit ddcf4ac

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+2394
-1481
lines changed

.github/workflows/build-intel.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,18 @@ jobs:
4747
source /opt/intel/oneapi/setvars.sh
4848
cmake --build build --parallel
4949
50+
# If the unit tests below are failing run to see details.
51+
# - name: Unit Test
52+
# shell: bash
53+
# run: |
54+
# source /opt/intel/oneapi/setvars.sh
55+
# export SYCL_DEVICE_FILTER=opencl.cpu
56+
# pwd
57+
# ls
58+
# ls build
59+
# ls build/bin
60+
# ./build/bin/unit_tests
61+
5062
- name: Test
5163
shell: bash
5264
run: |

CMakeLists.txt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,6 @@ else()
172172
set(CUDA_LIBRARY-NOTFOUND true)
173173
endif()
174174

175-
# option to force native termination, mostly for testing new GPU code
176-
# in comparison with the CPU
177-
option(CUPDLP_FORCE_NATIVE "Build pdlp with native termination" OFF)
178-
179175
if (BUILD_CXX)
180176
# Default Build Type to be Release
181177
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)

FEATURES.md

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,49 @@
22

33
## Code changes
44

5-
Fixed incorrect assertion in `HighsMipSolver::solutionFeasible()` (fixing [#2204](https://github.com/ERGO-Code/HiGHS/issues/2204)))
5+
Fixed incorrect assertion in `HighsMipSolver::solutionFeasible()` (fixing [#2204](https://github.com/ERGO-Code/HiGHS/issues/2204))
6+
7+
As part of [#2251](https://github.com/ERGO-Code/HiGHS/issues/2251) cuPDLP-C will start from the incumbent solution in HiGHS. For a model that has been changed, the user must supply a starting solution via a call to `Highs::setSolution`
68

79
getColIntegrality now returns `HighsVarType::kContinuous` when `model_.lp_.integrality_` is empty (fixing [#2261](https://github.com/ERGO-Code/HiGHS/issues/2261))
810

911
Now ensuring that when solving a scaled LP with useful but unvalidated basis, it does not lose its scaling after validation, since the scaling factors will be applied to the solution (fixing [#2267](https://github.com/ERGO-Code/HiGHS/issues/2267))
1012

1113
By setting non-empty values of options `read_solution_file`, `read_basis_file`, `write_model_file` (with extension `.lp` or `.mps`), `write_solution_file`, `solution_file`, `write_basis_file`, these files will be read or written when calling `Highs::run()`. Hence options previously only available via the command line interface can be use (for example) by modelling languages that only call `Highs::run()` (fixing [#2269](https://github.com/ERGO-Code/HiGHS/issues/2269)).
1214

13-
Bug [#2273](https://github.com/ERGO-Code/HiGHS/issues/2273)) fixed
15+
Bug [#2273](https://github.com/ERGO-Code/HiGHS/issues/2273) fixed
1416

15-
As part of [#2286](https://github.com/ERGO-Code/HiGHS/pull/2286)), the root of the HiGHS source files is now `highs/`, rather than `src/`
17+
As part of [#2286](https://github.com/ERGO-Code/HiGHS/pull/2286), the root of the HiGHS source files is now `highs/`, rather than `src/`
1618

1719
ZI rounding and shifting MIP primal heuristics have been added (see [#2287](https://github.com/ERGO-Code/HiGHS/pull/2287)). They are off by default, but can be activated by setting the options `mip_heuristic_run_zi_round` and `mip_heuristic_run_shifting` to be true. Options `mip_heuristic_run_rins`, `mip_heuristic_run_rens` and `mip_heuristic_run_root_reduced_cost` to run the RINS, RENS and rootReducedCost heuristics have been added. These are true by default, but setting them to be false can accelerate the MIP solver on easy problems.
1820

19-
Added `Highs_changeRowsBoundsByRange` to C API, fixing [#2296](https://github.com/ERGO-Code/HiGHS/issues/2296))
21+
Added `Highs_changeRowsBoundsByRange` to C API, fixing [#2296](https://github.com/ERGO-Code/HiGHS/issues/2296)
22+
23+
Corrected docstrings for `Highs_getReducedRow`, motivated by [#2312](https://github.com/ERGO-Code/HiGHS/issues/2312)
24+
25+
LP file reader no longer fails when there is no objective section. Fix is [#2316](https://github.com/ERGO-Code/HiGHS/pull/2316), but this exposes code quality issue [#2318](https://github.com/ERGO-Code/HiGHS/issues/2318)
26+
27+
Added a max scale factor (+1024) when scaling up coefficients in `preprocessBaseInequality` and `postprocessCut`. Fix is [#2337](https://github.com/ERGO-Code/HiGHS/pull/2337)
28+
29+
Corrected the bounds used in when strengthening coefficients in `HPresolve::rowPresolve`, fixing [#1517](https://github.com/ERGO-Code/HiGHS/issues/1517)
30+
31+
Fixed numerical error in `highs/mip/HighsCliqueTable.cpp`, closing [#2320](https://github.com/ERGO-Code/HiGHS/issues/2320)
32+
33+
Fixed bug in `highs/mip/HighsFeasibilityJump.cpp`, closing [#2331](https://github.com/ERGO-Code/HiGHS/issues/2331)
34+
35+
Tightened CMIR cuts, leading to small performance gain, closing [#2333](https://github.com/ERGO-Code/HiGHS/issues/2333)
36+
37+
Scaling the tolerance in forcing row reduction to avoid use of rows with small coefficients and bounds, closing [#2290](https://github.com/ERGO-Code/HiGHS/issues/2290)
38+
39+
Fixed bug when calculating a coefficient in one of the cuts in `separateImpliedBounds` in `highs/mip/HighsImplications.cpp`
40+
41+
Added `CSECTION` to the exceptions for keywords that are followed by text, and thus cannot be used as names of columns, RHS, ranges, bounds etc.
42+
43+
Introduced the following KKT error measures to `HighsInfo`: `num_relative_primal_infeasibilities`; `max_relative_primal_infeasibility`; `num_relative_dual_infeasibilities`; `max_relative_dual_infeasibility`; `num_primal_residual_errors`; `max_primal_residual_error`; `num_dual_residual_errors`; `max_dual_residual_error`; `num_relative_primal_residual_errors`; `max_relative_primal_residual_error`; `num_relative_dual_residual_errors`; `max_relative_dual_residual_error`; `num_complementarity_violations`; `max_complementarity_violation`; `primal_dual_objective_error.` The relative values are used to assess whether a solution deemed to be optimal by the first order LP solver `cuPDLP-C` or interior point solver `IPX` (without crossover) is truly acceptable. They also enable users to determine whether a solution corresponding to `HighsModelStatus::kUnknown` is acceptable to them as optimal. Also introduced options `complementarity_tolerance` used to assess whether the (relative) primal-dual objective error is acceptable, and `kkt_tolerance` which, if set to a value other than `kDefaultKktTolerance = 1e-7` is used as the tolerance for all the KKT error measures. The HiGHS documentation has been updated to reflect the new options and `HighsInfo` data, and logging messages indicate when KKT error measures are not satisfied, despite the solver considering the LP solution to be optimal.
44+
45+
2046

21-
Corrected docstrings for `Highs_getReducedRow`, motivated by [#2312](https://github.com/ERGO-Code/HiGHS/issues/2312))
2247

23-
LP file reader no longer fails when there is no objective section. Fix is [#2316](https://github.com/ERGO-Code/HiGHS/pull/2316)), but this exposes code quality issue [#2318](https://github.com/ERGO-Code/HiGHS/issues/2318))
2448

2549
Added a max scale factor (+1024) when scaling up coefficients in `preprocessBaseInequality` and `postprocessCut`. Fix is [#2337](https://github.com/ERGO-Code/HiGHS/pull/2337).
2650

app/RunHighs.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,12 @@ int main(int argc, char** argv) {
7575
// call this first so that printHighsVersionCopyright uses reporting
7676
// settings defined in any options file.
7777
highs.passOptions(loaded_options);
78-
// highs.writeOptions("Options.md");
7978
highs.writeOptions("", true);
8079

80+
// Lines to write out documentation of HighsOptions and HighsInfo
81+
// highs.writeOptions("Options.md");
82+
// highs.writeInfo("Info.md");
83+
8184
// Load the model from model_file
8285
HighsStatus read_status = highs.readModel(cmd_options.model_file);
8386
if (read_status == HighsStatus::kError) {
@@ -107,8 +110,6 @@ int main(int argc, char** argv) {
107110
HighsStatus run_status = highs.run();
108111
if (run_status == HighsStatus::kError) return int(run_status);
109112

110-
// highs.writeInfo("Info.md");
111-
112113
// Shut down task executor for explicit release of memory.
113114
// Valgrind still reachable otherwise.
114115
highs.resetGlobalScheduler(true);

check/CMakeLists.txt

Lines changed: 68 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -278,111 +278,88 @@ if ((NOT FAST_BUILD OR ALL_TESTS) AND NOT (BUILD_EXTRA_UNIT_ONLY))
278278
)
279279

280280
if (UNIX AND NOT APPLE AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
281-
if (CUPDLP_CPU AND NOT CUPDLP_FORCE_NATIVE)
281+
if (CUPDLP_GPU)
282282
set(pdlpInstances
283-
"25fv47\; 5.50184588\;"
284-
"adlittle\; 2.254949631\;"
285-
"afiro\;-4.64753142\;"
286-
"avgas\;-7.749999999\;"
283+
"25fv47\; 5.5018549\;"
284+
"adlittle\; 2.254950\;"
285+
"afiro\;-4.6475325\;"
286+
"avgas\;-7.75000038\;"
287287
"blending\;-3.19999999\;"
288-
"chip\;-9.000000001\;"
289-
"e226\;-1.16389293\;"
290-
"scrs8\; 9.042969511\;"
291-
"sctest\; 5.749999936\;"
292-
"shell\; 1.2088253460\;"
293-
"stair\;-2.51266951\;"
294-
"standata\; 1.257699499\;"
295-
"standgub\; 1.25769949\;"
288+
"chip\;-9.0000000\;"
289+
"e226\;-1.16389258\;"
290+
"scrs8\; 9.0429623\;"
291+
"sctest\; 5.750000001\;"
292+
"shell\; 1.20882535\;"
293+
"stair\;-2.5126695\;"
294+
"standata\; 1.25769951\;"
295+
"standgub\; 1.2576993\;"
296+
)
297+
else() # CUPDLP_CPU
298+
set(pdlpInstances
299+
"25fv47\; 5.5018469\;"
300+
"adlittle\; 2.254949\;"
301+
"afiro\;-4.64753150\;"
302+
"avgas\;-7.7499999\;"
303+
"blending\;-3.1999999\;"
304+
"chip\;-8.9999999\;"
305+
"e226\;-1.16389294\;"
306+
"scrs8\; 9.04297094\;"
307+
"sctest\; 5.75000000\;"
308+
"shell\; 1.20882534\;"
309+
"stair\;-2.51266942\;"
310+
"standata\; 1.25769944\;"
311+
"standgub\; 1.25769944\;"
296312
)
297-
else()
298-
if (CUPDLP_GPU)
299-
set(pdlpInstances
300-
"25fv47\; 5.5018549\;"
301-
"adlittle\; 2.254950\;"
302-
"afiro\;-4.6475325\;"
303-
"avgas\;-7.75000038\;"
304-
"blending\;-3.19999999\;"
305-
"chip\;-9.0000000\;"
306-
"e226\;-1.16389258\;"
307-
"scrs8\; 9.0429623\;"
308-
"sctest\; 5.750000001\;"
309-
"shell\; 1.20882535\;"
310-
"stair\;-2.5126695\;"
311-
"standata\; 1.25769951\;"
312-
"standgub\; 1.2576993\;"
313-
)
314-
else()
315-
# CUPDLP_GPU or CPU with native termination.
316-
if (CUPDLP_FORCE_NATIVE)
317-
set(pdlpInstances
318-
"25fv47\; 5.5018360\;"
319-
"adlittle\; 2.254953\;"
320-
"afiro\;-4.64753126\;"
321-
"avgas\;-7.75000038\;"
322-
"blending\;-3.19999999\;"
323-
"chip\;-9.000000020\;"
324-
"e226\;-1.163892070\;"
325-
"scrs8\; 9.042970154\;"
326-
"sctest\; 5.750000001\;"
327-
"shell\; 1.2088253471\;"
328-
"stair\;-2.512669020\;"
329-
"standata\; 1.257699155\;"
330-
"standgub\; 1.257700132\;"
331-
)
332-
endif()
333-
endif()
334313
endif()
335314
elseif(WIN32 AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
336-
if (CUPDLP_CPU AND NOT CUPDLP_FORCE_NATIVE)
315+
if (CUPDLP_GPU)
316+
set(pdlpInstances
317+
"25fv47\; 5.50185\;" # 549 release 500 debug
318+
"adlittle\; 2.2549505\;"
319+
"afiro\;-4.6475325\;"
320+
"avgas\;-7.750000\;"
321+
"blending\;-3.19999999\;"
322+
"chip\;-9.0000000\;"
323+
"scrs8\; 9.0429693\;"
324+
"sctest\; 5.7500000\;"
325+
"shell\; 1.20882535\;"
326+
"stair\;-2.512669\;" # 96 release 95 debug
327+
"standata\; 1.2576995\;"
328+
"standgub\; 1.2576993\;"
329+
)
330+
else() # CUPDLP_CPU
337331
# on windows e226 model status is unknown
338332
# on windows 25fv47 model status can be unknown, with objective 5.5018458957e+03
339333
set(pdlpInstances
340-
"25fv47\; 5.5018458\;"
341-
"adlittle\; 2.25494963\;"
342-
"afiro\;-4.64753142\;"
343-
"avgas\;-7.749999999\;"
334+
"25fv47\; 5.50184\;"
335+
"adlittle\; 2.25494944\;"
336+
"afiro\;-4.647531504\;"
337+
"avgas\;-7.7499999\;"
344338
"blending\;-3.19999999\;"
345-
"chip\;-9.000000001\;"
346-
"scrs8\; 9.0429695\;"
347-
"sctest\; 5.749999936\;"
348-
"shell\; 1.2088253460\;"
349-
"stair\;-2.51266951\;"
350-
"standata\; 1.2576995\;"
351-
"standgub\; 1.2576995\;"
339+
"chip\;-8.9999999\;"
340+
"scrs8\; 9.04297094\;"
341+
"sctest\; 5.7500000\;"
342+
"shell\; 1.20882534\;"
343+
"stair\;-2.51266942\;"
344+
"standata\; 1.257699393\;"
345+
"standgub\; 1.25769939\;"
352346
)
353-
else()
354-
if (CUPDLP_GPU)
355-
set(pdlpInstances
356-
"25fv47\; 5.50185\;" # 549 release 500 debug
357-
"adlittle\; 2.2549505\;"
358-
"afiro\;-4.6475325\;"
359-
"avgas\;-7.750000\;"
360-
"blending\;-3.19999999\;"
361-
"chip\;-9.0000000\;"
362-
"scrs8\; 9.0429693\;"
363-
"sctest\; 5.7500000\;"
364-
"shell\; 1.20882535\;"
365-
"stair\;-2.512669\;" # 96 release 95 debug
366-
"standata\; 1.2576995\;"
367-
"standgub\; 1.2576993\;"
368-
)
369-
endif()
370347
endif()
371348
elseif(APPLE)
372349
set(pdlpInstances
373-
"25fv47\; 5.5018458\;"
374-
"adlittle\; 2.25494963\;"
375-
"afiro\;-4.64753142\;"
376-
"avgas\;-7.749999999\;"
350+
"25fv47\; 5.501846\;"
351+
"adlittle\; 2.254949\;"
352+
"afiro\;-4.647531\;"
353+
"avgas\;-7.7499999\;"
377354
"blending\;-3.19999999\;"
378-
"chip\;-8.9999999\;"
379-
"e226\;-1.163892\;"
380-
"scrs8\; 9.0429695\;"
381-
"sctest\; 5.749999936\;"
382-
"shell\; 1.2088253460\;"
383-
"stair\;-2.5126695\;"
384-
"standata\; 1.25769950\;"
385-
"standgub\; 1.25769950\;"
355+
"chip\;-9.0000000\;"
356+
"e226\;-1.16389\;"
357+
"scrs8\; 9.04296\;"
358+
"sctest\; 5.75000000\;"
359+
"shell\; 1.20882535\;"
360+
"stair\;-2.5126\;"
361+
"standata\; 1.25769947\;"
362+
"standgub\; 1.2576994\;"
386363
)
387364
endif()
388365

check/SpecialLps.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ class SpecialLps {
334334

335335
void ThreeDLp(HighsLp& lp, HighsModelStatus& require_model_status,
336336
double& optimal_objective) {
337-
lp.model_name_ = "distillation";
337+
lp.model_name_ = "3-d LP";
338338
lp.num_col_ = 3;
339339
lp.num_row_ = 2;
340340
lp.col_cost_ = {1, 2, 3};

check/TestAlienBasis.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ void testAlienBasis(const bool avgas, const HighsInt seed) {
431431

432432
Highs highs;
433433
if (!dev_run) highs.setOptionValue("output_flag", false);
434+
434435
highs.readModel(filename);
435436
HighsLp lp = highs.getLp();
436437
HighsInt num_col = lp.num_col_;

check/TestEkk.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ TEST_CASE("Ekk", "[highs_test_ekk]") {
8080

8181
REQUIRE(highs.setOptionValue("simplex_strategy", kSimplexStrategyDual) ==
8282
HighsStatus::kOk);
83-
highs.setOptionValue("log_dev_level", kHighsLogDevLevelDetailed);
83+
if (dev_run)
84+
highs.setOptionValue("log_dev_level", kHighsLogDevLevelDetailed);
8485
REQUIRE(highs.run() == HighsStatus::kOk);
8586
} else {
8687
// ekk_distillation(highs);

check/TestLpModification.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ TEST_CASE("LP-modification", "[highs_data]") {
797797
REQUIRE(model_status == HighsModelStatus::kOptimal);
798798

799799
highs.getInfoValue("objective_function_value", optimal_objective_value);
800-
REQUIRE(optimal_objective_value == avgas_optimal_objective_value);
800+
REQUIRE(optimal_objective_value - avgas_optimal_objective_value < 1e-10);
801801

802802
// Fix columns 1, 3, 5, 7 to check resetting of their nonbasic status
803803
col1357_lower[0] = 0;
@@ -826,7 +826,7 @@ TEST_CASE("LP-modification", "[highs_data]") {
826826
callRun(highs, options.log_options, "highs.run()", HighsStatus::kOk);
827827

828828
highs.getInfoValue("objective_function_value", optimal_objective_value);
829-
REQUIRE(optimal_objective_value == avgas_optimal_objective_value);
829+
REQUIRE(optimal_objective_value - avgas_optimal_objective_value < 1e-10);
830830

831831
const HighsLp& local_lp = highs.getLp();
832832
row0135789_lower[0] = local_lp.row_lower_[0];
@@ -1145,8 +1145,10 @@ TEST_CASE("LP-interval-changes", "[highs_data]") {
11451145
const HighsOptions& options = highs.getOptions();
11461146
const HighsInfo& info = highs.getInfo();
11471147

1148-
highs.setOptionValue("log_to_console", true);
1149-
highs.setOptionValue("log_dev_level", kHighsLogDevLevelVerbose);
1148+
if (dev_run) {
1149+
highs.setOptionValue("log_to_console", true);
1150+
highs.setOptionValue("log_dev_level", kHighsLogDevLevelVerbose);
1151+
}
11501152

11511153
std::string model_file =
11521154
std::string(HIGHS_DIR) + "/check/instances/avgas.mps";

check/TestMipSolver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ TEST_CASE("MIP-nmck", "[highs_test_mip_solver]") {
207207
HighsVarType::kInteger};
208208
REQUIRE(highs.passModel(lp) == HighsStatus::kOk);
209209
highs.setOptionValue("highs_debug_level", kHighsDebugLevelCheap);
210-
highs.setOptionValue("log_dev_level", 2);
210+
if (dev_run) highs.setOptionValue("log_dev_level", 2);
211211
HighsStatus return_status = highs.run();
212212
REQUIRE(return_status == HighsStatus::kOk);
213213
if (dev_run) highs.writeInfo("");

0 commit comments

Comments
 (0)