Skip to content

Commit 51b2ceb

Browse files
committed
Merge branch 'latest' into bzl-san
2 parents 603b366 + e8c0584 commit 51b2ceb

31 files changed

Lines changed: 704 additions & 212 deletions

.github/workflows/hipo-mangle.yml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
name: hipo-mangle
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
check-metis:
7+
runs-on: ubuntu-latest
8+
strategy:
9+
fail-fast: false
10+
matrix:
11+
config: [Release]
12+
all_tests: [OFF]
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Checkout METIS
18+
uses: actions/checkout@v4
19+
with:
20+
repository: galabovaa/METIS
21+
ref: 510-w
22+
path: METIS
23+
24+
- name: Create installs dir
25+
working-directory: ${{runner.workspace}}
26+
run: |
27+
mkdir installs
28+
ls
29+
30+
- name: Install METIS
31+
run: |
32+
cmake \
33+
-S $GITHUB_WORKSPACE/METIS \
34+
-B build \
35+
-DGKLIB_PATH=${{ github.workspace }}/METIS/GKlib \
36+
-DCMAKE_INSTALL_PREFIX=${{ runner.workspace }}/installs
37+
cmake --build build
38+
cmake --install build
39+
40+
- name: Create Build Environment
41+
run: cmake -E make_directory ${{runner.workspace}}/build
42+
43+
- name: Configure CMake
44+
working-directory: ${{runner.workspace}}/build
45+
run: |
46+
cmake $GITHUB_WORKSPACE -DHIPO=ON -DBUILD_OPENBLAS=ON \
47+
-DALL_TESTS=${{ matrix.all_tests }}
48+
49+
- name: Build HiGHS
50+
working-directory: ${{runner.workspace}}/build
51+
run: |
52+
cmake --build . -j2
53+
54+
- name: Generate METIS symbols
55+
working-directory: ${{runner.workspace}}
56+
run: |
57+
nm installs/lib/libmetis.a | grep -e "[tT] [^ ]+$" -oE | sort > metis.txt
58+
59+
- name: Generate HiGHS symbols
60+
working-directory: ${{runner.workspace}}
61+
run: |
62+
nm build/lib/libhighs.a | grep -e "[tT] [^ ]+$" -oE | sort > highs.txt
63+
64+
- name: Compare symbols
65+
working-directory: ${{runner.workspace}}
66+
run: comm -12 highs.txt metis.txt > common.txt
67+
68+
- name: Check
69+
working-directory: ${{runner.workspace}}
70+
run: |
71+
if [[ "$(wc -l < common.txt)" -eq 0 ]]; then
72+
exit 0
73+
fi
74+
echo "Metis symbols"
75+
cat metis.txt
76+
echo "Highs symbols"
77+
cat highs.txt
78+
echo "Common symbols"
79+
cat compare.txt
80+
exit 1

check/TestCAPI.c

Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -241,16 +241,16 @@ void assertLogical(const char* name, const HighsInt is) {
241241
void createBlendingLp(void* highs) {
242242
// Special variant of the blending LP, with redundant constraint so
243243
// that LP is reduced by presolve - but not to empty!
244-
const double inf = Highs_getInfinity(highs);
244+
const double kHighsInf = Highs_getInfinity(highs);
245245

246246
HighsInt num_col = 2;
247247
HighsInt num_row = 3;
248248
HighsInt num_nz = 6;
249249
HighsInt sense = -1;
250250
double col_cost[2] = {8, 10};
251251
double col_lower[2] = {0, 0};
252-
double col_upper[2] = {inf, inf};
253-
double row_lower[3] = {-inf, -inf, -inf};
252+
double col_upper[2] = {kHighsInf, kHighsInf};
253+
double row_lower[3] = {-kHighsInf, -kHighsInf, -kHighsInf};
254254
double row_upper[3] = {500, 120, 210};
255255
HighsInt a_index[6] = {0, 1, 0, 1, 0, 1};
256256
double a_value[6] = {0.5, 0.5, 0.3, 0.5, 0.7, 0.5};
@@ -488,41 +488,64 @@ void minimalApiQp() {
488488
HighsInt num_col = 3;
489489
HighsInt num_row = 1;
490490
HighsInt num_nz = 2;
491-
HighsInt q_num_nz = 4;
492491
HighsInt a_format = kHighsMatrixFormatColwise;
493-
HighsInt q_format = kHighsHessianFormatTriangular;
494492
HighsInt sense = kHighsObjSenseMinimize;
495493
double offset = 0;
496494
double col_cost[3] = {0.0, -1.0, -3.0};
497495
double col_lower[3] = {-inf, -inf, -inf};
498496
double col_upper[3] = {inf, inf, inf};
499497
double row_lower[1] = {-inf};
500498
double row_upper[1] = {2};
499+
501500
HighsInt a_start[3] = {0, 1, 1};
502501
HighsInt a_index[2] = {0, 0};
503502
double a_value[2] = {1.0, 1.0};
503+
504+
// Start with triangular Hessian, then
505+
HighsInt q_format = kHighsHessianFormatTriangular;
506+
HighsInt q_num_nz = 4;
504507
HighsInt q_start[3] = {0, 2, 3};
505508
HighsInt q_index[4] = {0, 2, 1, 2};
506509
double q_value[4] = {2.0, -1.0, 0.2, 2.0};
507510

511+
double required_x[3] = {0.5, 5.0, 1.5};
512+
508513
double* col_value = (double*)malloc(sizeof(double) * num_col);
514+
509515
HighsInt model_status;
510-
HighsInt return_status = Highs_qpCall(
511-
num_col, num_row, num_nz, q_num_nz, a_format, q_format, sense, offset,
512-
col_cost, col_lower, col_upper, row_lower, row_upper, a_start, a_index,
513-
a_value, q_start, q_index, q_value, col_value, NULL, NULL, NULL, NULL,
514-
NULL, &model_status);
516+
HighsInt return_status =
517+
Highs_qpCall(num_col, num_row, num_nz, q_num_nz, a_format, q_format, sense, offset,
518+
col_cost, col_lower, col_upper, row_lower, row_upper, a_start, a_index,
519+
a_value, q_start, q_index, q_value, col_value, NULL, NULL, NULL, NULL,
520+
NULL, &model_status);
515521
assert(return_status == kHighsStatusOk);
516522
assertIntValuesEqual("Model status for QP qph", model_status,
517-
kHighsModelStatusOptimal);
518-
double required_x[3] = {0.5, 5.0, 1.5};
519-
if (dev_run) {
520-
for (HighsInt iCol = 0; iCol < num_col; iCol++) {
521-
printf("x%d1 = %g\n", (int)iCol, col_value[iCol]);
522-
assertDoubleValuesEqual("Solution value for QP qph", col_value[iCol],
523-
required_x[iCol]);
524-
}
523+
kHighsModelStatusOptimal);
524+
for (HighsInt iCol = 0; iCol < num_col; iCol++) {
525+
if (dev_run) printf("x%d1 = %g\n", (int)iCol, col_value[iCol]);
526+
assertDoubleValuesEqual("Solution value for QP qph", col_value[iCol],
527+
required_x[iCol]);
525528
}
529+
530+
HighsInt square_q_format = kHighsHessianFormatSquare;
531+
HighsInt square_q_num_nz = 5;
532+
HighsInt square_q_start[3] = {0, 2, 3};
533+
HighsInt square_q_index[5] = {0, 2, 1, 0, 2};
534+
double square_q_value[5] = {2.0, -1.0, 0.2, -1.0, 2.0};
535+
536+
Highs_qpCall(num_col, num_row, num_nz, square_q_num_nz, a_format, square_q_format, sense, offset,
537+
col_cost, col_lower, col_upper, row_lower, row_upper, a_start, a_index,
538+
a_value, square_q_start, square_q_index, square_q_value, col_value, NULL, NULL, NULL, NULL,
539+
NULL, &model_status);
540+
assert(return_status == kHighsStatusOk);
541+
assertIntValuesEqual("Model status for QP qph", model_status,
542+
kHighsModelStatusOptimal);
543+
for (HighsInt iCol = 0; iCol < num_col; iCol++) {
544+
if (dev_run) printf("x%d1 = %g\n", (int)iCol, col_value[iCol]);
545+
assertDoubleValuesEqual("Solution value for QP qph", col_value[iCol],
546+
required_x[iCol]);
547+
}
548+
526549
free(col_value);
527550
}
528551

@@ -1513,23 +1536,33 @@ void testPassHessian() {
15131536
HighsInt index[1] = {0};
15141537
double value[1] = {-2.0};
15151538
HighsInt return_status;
1516-
return_status = Highs_passHessian(highs, 1, 1, 1, start, index, value);
1517-
assertIntValuesEqual("Return of passHessian", return_status, kHighsStatusOk);
1518-
Highs_run(highs);
1519-
// Solving max -x^2 + 2x
1539+
15201540
const double optimal_objective_value = 1;
15211541
const double primal = 1;
15221542
const double dual = 0;
1523-
assertIntValuesEqual("Status", Highs_getModelStatus(highs),
1524-
kHighsModelStatusOptimal); // kOptimal
15251543
double col_value[1] = {-123.0};
15261544
double col_dual[1] = {0.0};
1527-
Highs_getSolution(highs, col_value, col_dual, NULL, NULL);
1528-
double objective_value = Highs_getObjectiveValue(highs);
1529-
assertDoubleValuesEqual("Objective", objective_value,
1530-
optimal_objective_value);
1531-
assertDoubleValuesEqual("Primal", col_value[0], primal);
1532-
assertDoubleValuesEqual("Dual", col_dual[0], dual);
1545+
1546+
for (HighsInt k = 0; k < 2; k++) {
1547+
HighsInt q_format = -1;
1548+
if (k == 0) {
1549+
q_format = kHighsHessianFormatTriangular;
1550+
} else {
1551+
q_format = kHighsHessianFormatSquare;
1552+
}
1553+
return_status = Highs_passHessian(highs, 1, 1, q_format, start, index, value);
1554+
assertIntValuesEqual("Return of passHessian", return_status, kHighsStatusOk);
1555+
Highs_run(highs);
1556+
// Solving max -x^2 + 2x
1557+
assertIntValuesEqual("Status", Highs_getModelStatus(highs),
1558+
kHighsModelStatusOptimal); // kOptimal
1559+
Highs_getSolution(highs, col_value, col_dual, NULL, NULL);
1560+
double objective_value = Highs_getObjectiveValue(highs);
1561+
assertDoubleValuesEqual("Objective", objective_value,
1562+
optimal_objective_value);
1563+
assertDoubleValuesEqual("Primal", col_value[0], primal);
1564+
assertDoubleValuesEqual("Dual", col_dual[0], dual);
1565+
}
15331566

15341567
Highs_destroy(highs);
15351568
}

check/TestMipSolver.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,3 +1404,26 @@ TEST_CASE("issue-2173", "[highs_test_mip_solver]") {
14041404
const double optimal_objective = -26770.8075489;
14051405
solve(highs, kHighsOnString, require_model_status, optimal_objective);
14061406
}
1407+
1408+
TEST_CASE("issue-2957", "[highs_test_mip_solver]") {
1409+
HighsLp lp;
1410+
lp.num_col_ = 2;
1411+
lp.num_row_ = 1;
1412+
lp.col_cost_ = {1, 2};
1413+
lp.col_lower_ = {0, 8};
1414+
lp.col_upper_ = {20, 20};
1415+
lp.integrality_ = {HighsVarType::kInteger, HighsVarType::kContinuous};
1416+
lp.row_lower_ = {20.1};
1417+
lp.row_upper_ = {kHighsInf};
1418+
lp.a_matrix_.start_ = {0, 1, 2};
1419+
lp.a_matrix_.index_ = {0, 0};
1420+
lp.a_matrix_.value_ = {1, 1};
1421+
Highs highs;
1422+
highs.setOptionValue("output_flag", dev_run);
1423+
highs.setOptionValue("mip_rel_gap", 0);
1424+
highs.setOptionValue("mip_abs_gap", 0);
1425+
highs.passModel(lp);
1426+
const HighsModelStatus require_model_status = HighsModelStatus::kOptimal;
1427+
const double optimal_objective = 28.2;
1428+
solve(highs, kHighsOnString, require_model_status, optimal_objective);
1429+
}

check/TestQpSolver.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,6 +1318,50 @@ TEST_CASE("issue-2821", "[qpsolver]") {
13181318
h.resetGlobalScheduler(true);
13191319
}
13201320

1321+
TEST_CASE("pass-square-hessian", "[qpsolver]") {
1322+
Highs h;
1323+
h.setOptionValue("output_flag", dev_run);
1324+
const HighsInfo& info = h.getInfo();
1325+
// Set up the same constraints as 2821, but use a Hessian with more
1326+
// entries and varied values
1327+
HighsModel model;
1328+
HighsLp& lp = model.lp_;
1329+
HighsHessian& hessian = model.hessian_;
1330+
lp.num_col_ = 5;
1331+
lp.num_row_ = 3;
1332+
lp.col_cost_ = {0, -4, -4, -2, -2};
1333+
lp.col_lower_ = {0, 0, 0, 0, 0};
1334+
lp.col_upper_ = {inf, inf, inf, inf, inf};
1335+
lp.row_lower_ = {4, 0, 0};
1336+
lp.row_upper_ = {4, 0, 0};
1337+
lp.a_matrix_.start_ = {0, 1, 3, 4, 5, 7};
1338+
lp.a_matrix_.index_ = {0, 0, 2, 1, 1, 1, 2};
1339+
lp.a_matrix_.value_ = {1, 3, 1, 1, 1, -2, -1};
1340+
hessian.dim_ = lp.num_col_;
1341+
hessian.start_ = {0, 3, 6, 9, 11, 12};
1342+
hessian.index_ = {0, 1, 3, 1, 2, 3, 2, 3, 4, 3, 4, 4};
1343+
hessian.value_ = {4, -1, 1, 8, -2, 3, 9, -3, 2, 6, -4, 5};
1344+
const double optimal_objective_value = -1.9875776398e-01;
1345+
REQUIRE(h.passModel(model) == HighsStatus::kOk);
1346+
1347+
REQUIRE(h.run() == HighsStatus::kOk);
1348+
REQUIRE(okValueDifference(info.objective_function_value,
1349+
optimal_objective_value));
1350+
HighsHessian square_hessian = h.getModel().hessian_.toSquare();
1351+
REQUIRE(h.passHessian(square_hessian) == HighsStatus::kOk);
1352+
REQUIRE(h.run() == HighsStatus::kOk);
1353+
REQUIRE(okValueDifference(info.objective_function_value,
1354+
optimal_objective_value));
1355+
model.hessian_ = square_hessian;
1356+
REQUIRE(h.passModel(model) == HighsStatus::kOk);
1357+
1358+
REQUIRE(h.run() == HighsStatus::kOk);
1359+
REQUIRE(okValueDifference(info.objective_function_value,
1360+
optimal_objective_value));
1361+
1362+
h.resetGlobalScheduler(true);
1363+
}
1364+
13211365
/*
13221366
// This case causes a segfault with the meson build, but not with
13231367
// cmake. Might be indicative of the bug causing the degeneracy

cmake/sources.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ set(hipo_orderings_headers
304304
../extern/metis/GKlib/gk_arch.h
305305
../extern/metis/GKlib/gk_defs.h
306306
../extern/metis/GKlib/gk_macros.h
307+
../extern/metis/GKlib/gk_mangle.h
307308
../extern/metis/GKlib/gk_mkblas.h
308309
../extern/metis/GKlib/gk_mkmemory.h
309310
../extern/metis/GKlib/gk_mkpqueue.h
@@ -319,6 +320,7 @@ set(hipo_orderings_headers
319320
../extern/metis/libmetis/defs.h
320321
../extern/metis/libmetis/gklib_defs.h
321322
../extern/metis/libmetis/macros.h
323+
../extern/metis/libmetis/metis_mangle.h
322324
../extern/metis/libmetis/metislib.h
323325
../extern/metis/libmetis/proto.h
324326
../extern/metis/libmetis/stdheaders.h

extern/amd/amd_1.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
#include "amd_internal.h"
2828

29-
void amd_1
29+
void Highs_amd_1
3030
(
3131
amd_int n, /* n > 0 */
3232
const amd_int Ap [ ], /* input of size n+1, not modified */

extern/amd/amd_2.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
/* === clear_flag ========================================================== */
2020
/* ========================================================================= */
2121

22-
static amd_int clear_flag (amd_int wflg, amd_int wbig, amd_int W [ ], amd_int n)
22+
static amd_int Highs_amd_clear_flag (amd_int wflg, amd_int wbig, amd_int W [ ], amd_int n)
2323
{
2424
amd_int x ;
2525
if (wflg < 2 || wflg >= wbig)
@@ -624,7 +624,7 @@ void Highs_amd_2
624624

625625
/* initialize wflg */
626626
wbig = amd_int_max - n ;
627-
wflg = clear_flag (0, wbig, W, n) ;
627+
wflg = Highs_amd_clear_flag (0, wbig, W, n) ;
628628

629629
/* --------------------------------------------------------------------- */
630630
/* initialize degree lists and eliminate dense and empty rows */
@@ -992,7 +992,7 @@ void Highs_amd_2
992992
/* With the current value of wflg, wflg+n must not cause integer
993993
* overflow */
994994

995-
wflg = clear_flag (wflg, wbig, W, n) ;
995+
wflg = Highs_amd_clear_flag (wflg, wbig, W, n) ;
996996

997997
/* ========================================================================= */
998998
/* COMPUTE (W [e] - wflg) = |Le\Lme| FOR ALL ELEMENTS */
@@ -1274,7 +1274,7 @@ void Highs_amd_2
12741274
/* make sure that wflg+n does not cause integer overflow */
12751275
lemax = MAX (lemax, degme) ;
12761276
wflg += lemax ;
1277-
wflg = clear_flag (wflg, wbig, W, n) ;
1277+
wflg = Highs_amd_clear_flag (wflg, wbig, W, n) ;
12781278
/* at this point, W [0..n-1] < wflg holds */
12791279

12801280
/* ========================================================================= */
@@ -1682,7 +1682,7 @@ void Highs_amd_2
16821682
/* postorder the assembly tree */
16831683
/* ========================================================================= */
16841684

1685-
amd_postorder (n, Pe, Nv, Elen,
1685+
Highs_amd_postorder (n, Pe, Nv, Elen,
16861686
W, /* output order */
16871687
Head, Next, Last) ; /* workspace */
16881688

extern/amd/amd_aat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
#include "amd_internal.h"
1919

20-
size_t amd_aat /* returns nz in A+A' */
20+
size_t Highs_amd_aat /* returns nz in A+A' */
2121
(
2222
amd_int n,
2323
const amd_int Ap [ ],

0 commit comments

Comments
 (0)