Skip to content

Commit a0a733f

Browse files
authored
Merge pull request #2699 from ERGO-Code/hipo-orderings
Add Metis, AMD and RCM to HiGHS
2 parents 9cc4f4f + cd2bd0b commit a0a733f

Some content is hidden

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

98 files changed

+12988
-339
lines changed

LicenseNote.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
The HiGHS source code in highs/ is available under MIT
2+
license (see LICENSE.TXT).
3+
4+
Some of the code in extern/ is available under other
5+
similar permissive licenses:
6+
- SuiteSparse AMD is available under BSD 3-clause license.
7+
- Metis is available under Apache 2.0 license.
8+
9+
These codes ara needed only when building HiGHS with HiPO
10+
support (-DHIPO=ON). If this is the case, then the resulting
11+
HiGHS library and executables are available with Apache 2.0
12+
license rather than MIT.

check/TestHipo.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,55 @@ TEST_CASE("test-hipo-deterministic", "[highs_hipo]") {
8484
REQUIRE(solution_1.row_value == solution_2.row_value);
8585
REQUIRE(solution_1.col_dual == solution_2.col_dual);
8686
REQUIRE(solution_1.row_dual == solution_2.row_dual);
87+
}
88+
89+
TEST_CASE("test-hipo-orderings", "[highs_hipo]") {
90+
// Test that hipo orderings work correctly
91+
92+
std::string model = "adlittle.mps";
93+
const double expected_obj = 2.2549e5;
94+
95+
Highs highs;
96+
highs.setOptionValue("output_flag", dev_run);
97+
highs.setOptionValue("solver", kHipoString);
98+
highs.setOptionValue("timeless_log", kHighsOnString);
99+
100+
std::string filename = std::string(HIGHS_DIR) + "/check/instances/" + model;
101+
highs.readModel(filename);
102+
103+
// metis
104+
{
105+
highs.setOptionValue(kHipoOrderingString, kHipoMetisString);
106+
HighsStatus status = highs.run();
107+
REQUIRE(status == HighsStatus::kOk);
108+
109+
const double actual_obj = highs.getObjectiveValue();
110+
111+
REQUIRE(std::abs(actual_obj - expected_obj) / std::abs(expected_obj) <
112+
1e-4);
113+
}
114+
115+
// amd
116+
{
117+
highs.setOptionValue(kHipoOrderingString, kHipoAmdString);
118+
HighsStatus status = highs.run();
119+
REQUIRE(status == HighsStatus::kOk);
120+
121+
const double actual_obj = highs.getObjectiveValue();
122+
REQUIRE(std::abs(actual_obj - expected_obj) / std::abs(expected_obj) <
123+
1e-4);
124+
}
125+
126+
// rcm
127+
{
128+
highs.setOptionValue(kHipoOrderingString, kHipoRcmString);
129+
HighsStatus status = highs.run();
130+
REQUIRE(status == HighsStatus::kOk);
131+
132+
const double actual_obj = highs.getObjectiveValue();
133+
REQUIRE(std::abs(actual_obj - expected_obj) / std::abs(expected_obj) <
134+
1e-4);
135+
}
136+
137+
highs.resetGlobalScheduler(true);
87138
}

cmake/FindHipoDeps.cmake

Lines changed: 0 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -144,108 +144,3 @@ else()
144144
endif()
145145
endif()
146146
endif()
147-
148-
# METIS
149-
set(METIS_ROOT "" CACHE STRING "Root directory of METIS")
150-
message(STATUS "METIS_ROOT is " ${METIS_ROOT})
151-
152-
# If a METIS install was specified try to use it first.
153-
if (NOT (METIS_ROOT STREQUAL ""))
154-
message(STATUS "Looking for METIS CMake targets file in " ${METIS_ROOT})
155-
find_package(metis CONFIG NO_DEFAULT_PATH QUIET)
156-
else()
157-
find_package(metis CONFIG QUIET)
158-
endif()
159-
160-
if(metis_FOUND)
161-
message(STATUS "metis CMake config path: ${metis_DIR}")
162-
else()
163-
find_path(METIS_PATH
164-
NAMES "metis.h"
165-
PATHS "${METIS_ROOT}/include"
166-
NO_DEFAULT_PATH)
167-
168-
message(STATUS "Found Metis header at ${METIS_PATH}")
169-
170-
find_library(METIS_LIB
171-
NAMES metis libmetis
172-
PATHS "${METIS_ROOT}/lib" "${METIS_ROOT}/bin"
173-
NO_DEFAULT_PATH)
174-
175-
if(METIS_LIB)
176-
message(STATUS "Found Metis library at ${METIS_LIB}")
177-
else()
178-
# METIS_ROOT was not successful
179-
message(STATUS "Metis not found in METIS_PATH, fallback to default search.")
180-
if (NOT (METIS_ROOT STREQUAL ""))
181-
find_package(metis CONFIG)
182-
183-
if (metis_FOUND)
184-
message(STATUS "metis CMake config path: ${metis_DIR}")
185-
else()
186-
# METIS_ROOT was not successful and there is no cmake config
187-
find_path(METIS_PATH
188-
NAMES "metis.h")
189-
190-
message(STATUS "Found Metis header at ${METIS_PATH}")
191-
192-
find_library(METIS_LIB
193-
NAMES metis libmetis)
194-
195-
if(METIS_LIB)
196-
message(STATUS "Found Metis library at ${METIS_LIB}")
197-
else()
198-
message(FATAL_ERROR "No Metis library found")
199-
endif()
200-
endif()
201-
endif()
202-
endif()
203-
endif()
204-
205-
# GKlib optional for newer versions on ubuntu and macos
206-
set(GKLIB_ROOT "" CACHE STRING "Root directory of GKlib")
207-
if (NOT (GKLIB_ROOT STREQUAL ""))
208-
message(STATUS "GKLIB_ROOT is " ${GKLIB_ROOT})
209-
210-
find_package(GKlib CONFIG NO_DEFAULT_PATH)
211-
212-
if(GKlib_FOUND)
213-
message(STATUS "gklib CMake config path: ${GKlib_DIR}")
214-
215-
# get_cmake_property(_vars VARIABLES)
216-
# foreach(_v IN LISTS _vars)
217-
# if(_v MATCHES "GKlib")
218-
# message(STATUS "${_v} = ${${_v}}")
219-
# endif()
220-
# endforeach()
221-
222-
# get_property(_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY IMPORTED_TARGETS)
223-
# foreach(_t IN LISTS _targets)
224-
# if(_t MATCHES "GKlib")
225-
# message(STATUS "GKlib exported target: ${_t}")
226-
# endif()
227-
# endforeach()
228-
229-
else()
230-
find_path(GKLIB_PATH
231-
NAMES "gklib.h" "GKlib.h"
232-
REQUIRED
233-
PATHS "${GKLIB_ROOT}/include"
234-
NO_DEFAULT_PATH)
235-
236-
message(STATUS "Found GKlib header at ${GKLIB_PATH}")
237-
238-
find_library(GKLIB_LIB
239-
NAMES GKlib libGKlib
240-
REQUIRED
241-
PATHS "${GKLIB_ROOT}/lib"
242-
NO_DEFAULT_PATH)
243-
244-
if(GKLIB_LIB)
245-
message(STATUS "Found GKlib library at ${GKLIB_LIB}")
246-
else()
247-
# GKLIB_ROOT was not successful
248-
message(FATAL_ERROR "No GKlib library found at ${GKLIB_ROOT}")
249-
endif()
250-
endif()
251-
endif()

cmake/sources.cmake

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,74 @@ set(hipo_util_headers
258258
ipm/hipo/auxiliary/mycblas.h
259259
ipm/hipo/auxiliary/VectorOperations.h)
260260

261+
set(hipo_orderings_sources
262+
../extern/amd/amd_1.c
263+
../extern/amd/amd_2.c
264+
../extern/amd/amd_aat.c
265+
../extern/amd/amd_control.c
266+
../extern/amd/amd_defaults.c
267+
../extern/amd/amd_info.c
268+
../extern/amd/amd_order.c
269+
../extern/amd/amd_post_tree.c
270+
../extern/amd/amd_postorder.c
271+
../extern/amd/amd_preprocess.c
272+
../extern/amd/amd_valid.c
273+
../extern/amd/SuiteSparse_config.c
274+
../extern/metis/GKlib/error.c
275+
../extern/metis/GKlib/mcore.c
276+
../extern/metis/GKlib/memory.c
277+
../extern/metis/GKlib/random.c
278+
../extern/metis/libmetis/auxapi.c
279+
../extern/metis/libmetis/balance.c
280+
../extern/metis/libmetis/bucketsort.c
281+
../extern/metis/libmetis/coarsen.c
282+
../extern/metis/libmetis/compress.c
283+
../extern/metis/libmetis/contig.c
284+
../extern/metis/libmetis/fm.c
285+
../extern/metis/libmetis/gklib.c
286+
../extern/metis/libmetis/graph.c
287+
../extern/metis/libmetis/initpart.c
288+
../extern/metis/libmetis/mcutil.c
289+
../extern/metis/libmetis/mmd.c
290+
../extern/metis/libmetis/ometis.c
291+
../extern/metis/libmetis/options.c
292+
../extern/metis/libmetis/refine.c
293+
../extern/metis/libmetis/separator.c
294+
../extern/metis/libmetis/sfm.c
295+
../extern/metis/libmetis/srefine.c
296+
../extern/metis/libmetis/util.c
297+
../extern/metis/libmetis/wspace.c
298+
../extern/rcm/rcm.cpp)
299+
300+
set(hipo_orderings_headers
301+
../extern/amd/amd_internal.h
302+
../extern/amd/amd.h
303+
../extern/amd/SuiteSparse_config.h
304+
../extern/metis/GKlib/gk_arch.h
305+
../extern/metis/GKlib/gk_defs.h
306+
../extern/metis/GKlib/gk_macros.h
307+
../extern/metis/GKlib/gk_mkblas.h
308+
../extern/metis/GKlib/gk_mkmemory.h
309+
../extern/metis/GKlib/gk_mkpqueue.h
310+
../extern/metis/GKlib/gk_mkrandom.h
311+
../extern/metis/GKlib/gk_mksort.h
312+
../extern/metis/GKlib/gk_ms_inttypes.h
313+
../extern/metis/GKlib/gk_ms_stat.h
314+
../extern/metis/GKlib/gk_ms_stdint.h
315+
../extern/metis/GKlib/gk_proto.h
316+
../extern/metis/GKlib/gk_struct.h
317+
../extern/metis/GKlib/gk_types.h
318+
../extern/metis/GKlib/GKlib.h
319+
../extern/metis/libmetis/defs.h
320+
../extern/metis/libmetis/gklib_defs.h
321+
../extern/metis/libmetis/macros.h
322+
../extern/metis/libmetis/metislib.h
323+
../extern/metis/libmetis/proto.h
324+
../extern/metis/libmetis/stdheaders.h
325+
../extern/metis/libmetis/struct.h
326+
../extern/metis/metis.h
327+
../extern/rcm/rcm.h)
328+
261329
# redefinition of 'kHighsInf'
262330
set_source_files_properties (../extern/filereaderlp/reader.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
263331

docs/src/installation.md

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ HiGHS uses CMake as build system, and requires at least version
77

88
## HiGHS with HiPO
99

10-
HiGHS does not have any external dependencies, however, the new interior point solver HiPO uses BLAS and Metis. At the moment HiPO is optional and can be enabled via CMake. To build HiPO, you need to have Metis and BLAS installed on your machine. Please follow the instructions below.
10+
HiGHS does not have any external dependencies, however, the new interior point solver HiPO uses BLAS. At the moment HiPO is optional and can be enabled via CMake. To build HiPO, you need to have BLAS installed on your machine. Please follow the instructions below.
1111

1212
#### BLAS
1313

@@ -29,35 +29,15 @@ Note, that `[threads]` is required for HiPO.
2929

3030
To specify explicitly which BLAS vendor to look for, `BLA_VENDOR` coud be set in CMake, e.g. `-DBLA_VENDOR=Apple` or `-DBLA_VENDOR=OpenBLAS`. Alternatively, to specify which BLAS library to use, set `BLAS_LIBRARIES` to the full path of the library e.g. `-DBLAS_LIBRARIES=/path_to/libopenblas.so`.
3131

32-
#### Metis
33-
There are some known issues with Metis so the recommented version is in [this fork](https://github.com/galabovaa/METIS/tree/521-ts), branch 521-ts. This is version 5.2.1 with several patches for more reliable build and execution. Clone the repository with
34-
```
35-
git clone https://github.com/galabovaa/METIS.git
36-
cd METIS
37-
git checkout 521-ts
38-
```
39-
40-
Then build with
41-
```
42-
cmake -S. -B build \
43-
-DGKLIB_PATH=/path_to_METIS_repo/GKlib \
44-
-DCMAKE_INSTALL_PREFIX=path_to_installs_dir
45-
cmake --build build
46-
cmake --install build
47-
```
48-
49-
On Windows, do not forget to specify configuration type
50-
```
51-
cmake --build build --config Release
52-
```
32+
#### External ordering heuristics
5333

54-
If you compile HiGHS with 64-bit integers (HIGHSINT64=ON), then Metis must also be compiled with 64-bit integers.
34+
HiPO also relies on a fill-reducing ordering heuristic. HiGHS includes the source code of Metis, AMD and RCM, three open-source ordering heuristics. Their source code is already part of the HiGHS library, so there is no need to link them. In particular, there is no need to have Metis installed separately, as in previous versions of HiPO. These source codes can be found in extern/metis, extern/amd, extern/rcm, together with the respective license files. Notice that the HiGHS source code is MIT licensed. However, if you build HiGHS with HiPO support, then libhighs and the HiGHS executables are licensed Apache 2.0, due to the presence of Metis and AMD.
5535

5636
### HiPO
5737

5838
To install HiPO, on Linux and MacOS, run
5939
```
60-
cmake -S. -B build -DHIPO=ON -DMETIS_ROOT=path_to_installs_dir
40+
cmake -S. -B build -DHIPO=ON
6141
```
6242
On Windows, you also need to specify the path to OpenBLAS. If it was installed with vcpkg as suggested above, add the path to `vcpkg.cmake` to the CMake flags, e.g.
6343
```

docs/src/options/definitions.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -434,17 +434,17 @@
434434
- Type: string
435435
- Default: "both"
436436

437+
## [hipo\_ordering](@id option-hipo-ordering)
438+
- HiPO matrix reordering: "metis", "amd", "rcm" or "choose"
439+
- Type: string
440+
- Default: "choose"
441+
437442
## hipo\_block\_size
438443
- Block size for dense linear algebra within HiPO
439444
- Type: integer
440445
- Range: {0, 2147483647}
441446
- Default: 128
442447

443-
## [hipo\_metis\_no2hop](@id option-hipo-metis-no2hop)
444-
- Set option no2hop in Metis when using HiPO
445-
- Type: boolean
446-
- Default: false
447-
448448
## pdlp\_scaling
449449
- Scaling option for PDLP solver: Default = true
450450
- Type: boolean

docs/src/solvers.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,10 @@ HiGHS has two interior point (IPM) solvers:
5151
within the interior point solver: select "augmented" to force the solver to use the augmented system, "normaleq" for normal
5252
equations, or "choose" to leave the choice to the solver.
5353

54-
HiPO uses Metis internally to reorder the Newton system matrix. In case of large fill-in in the factorisation, two alternatives are available for users to try:
55-
* Setting the [hipo\_metis\_no2hop](@ref option-hipo-metis-no2hop) option to "true" may improve the quality of the ordering in some cases.
56-
* Linking the Metis library from branch 510-ts in [this fork](https://github.com/galabovaa/METIS/tree/510-ts), instead of branch 521-ts, may improve the quality of the ordering in some cases. This is available only if HiGHS is compiled from source.
54+
The option [hipo\_ordering](@ref option-hipo-ordering) can be used to select the fill-reducing heuristic to use during the factorisation:
55+
* Nested dissection, obtained setting the option [hipo\_ordering](@ref option-hipo-ordering) to "metis".
56+
* Approximate mininum degree, obtained setting the option [hipo\_ordering](@ref option-hipo-ordering) to "amd".
57+
* Reverse Cuthill-McKee, obtained setting the option [hipo\_ordering](@ref option-hipo-ordering) to "rcm".
5758

5859
Setting the option [__solver__](@ref option-solver) to "ipm" selects the HiPO solver, if the build supports it, otherwise it selects the IPX solver.
5960

extern/amd/License.txt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
AMD, Copyright (c), 1996-2022, Timothy A. Davis,
2+
Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved.
3+
4+
Availability:
5+
6+
http://www.suitesparse.com
7+
8+
-------------------------------------------------------------------------------
9+
AMD License: BSD 3-clause:
10+
-------------------------------------------------------------------------------
11+
12+
Redistribution and use in source and binary forms, with or without
13+
modification, are permitted provided that the following conditions are met:
14+
* Redistributions of source code must retain the above copyright
15+
notice, this list of conditions and the following disclaimer.
16+
* Redistributions in binary form must reproduce the above copyright
17+
notice, this list of conditions and the following disclaimer in the
18+
documentation and/or other materials provided with the distribution.
19+
* Neither the name of the organizations to which the authors are
20+
affiliated, nor the names of its contributors may be used to endorse
21+
or promote products derived from this software without specific prior
22+
written permission.
23+
24+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
28+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
34+
DAMAGE.
35+

0 commit comments

Comments
 (0)