Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
214 commits
Select commit Hold shift + click to select a range
2490b29
adding HighsMipWorker and HighsSearchWorker classes for a clean start
galabovaa Feb 13, 2025
e3a4ec3
undo changes from HighsSearchWorker from parallel-MIP
galabovaa Feb 13, 2025
057f653
methods in HighsSearchWorker clean up
galabovaa Feb 13, 2025
54d338f
new classes initializing in HighsMipSolver
galabovaa Feb 13, 2025
95c1711
added solution members, const mipdata ref, global cutpool to HighsMip…
galabovaa Feb 19, 2025
13f11c4
added most getters
galabovaa Feb 19, 2025
2d3de4d
initialize lps and workers in mipdata
galabovaa Feb 19, 2025
267f01f
using new search
galabovaa Feb 19, 2025
f43d22f
clean up highssearchworker
galabovaa Feb 19, 2025
2073b0c
clean up
galabovaa Feb 19, 2025
f22d9e1
heuristics on, all tests passing
galabovaa Feb 19, 2025
14ac63d
WIP
galabovaa Feb 19, 2025
bc04e0c
go to refactor more!
galabovaa Feb 20, 2025
3caa540
trying to init mipworker deque
galabovaa Feb 20, 2025
76f2b8a
WIP
galabovaa Feb 21, 2025
89ee858
primal heuristics, mipworker clean, init segfault on mipdata, highsdo…
galabovaa Feb 24, 2025
0d4d922
comment out offending code, find another way to init first worker
galabovaa Feb 24, 2025
32bfbf2
master worker initialized in mipdata deque from mipsolver just before…
galabovaa Feb 24, 2025
ec595c2
lprelaxation changed to ref in mipworker pointing to member of mipdat…
galabovaa Feb 25, 2025
18bc713
highscliquetable check
galabovaa Feb 26, 2025
69cbecf
Merged parallel-MIP into this branch
jajhall Feb 26, 2025
8b4485b
solution added to highsmipworker, format
galabovaa Feb 27, 2025
719253e
addIncumbent added in mipworker, not tested yet.
galabovaa Feb 27, 2025
d8abdc7
HighsSeparation done
galabovaa Feb 27, 2025
7f3e851
mipdata domain propagation off in HighsDomain
galabovaa Feb 27, 2025
90de58f
globaldom const in HighsDomain
galabovaa Feb 27, 2025
b17d159
more on HighsRedcostFixing, HighsSeparation, HighsLpRelaxation more …
galabovaa Feb 28, 2025
8ed2844
HighsCutGeneration
galabovaa Feb 28, 2025
a55efe6
initializing worker array OK: addIncumbent WIP
galabovaa Mar 4, 2025
b9ad017
clean up
galabovaa Mar 4, 2025
9c852dc
merge latest
galabovaa Apr 30, 2025
66dc66e
clear compile errors
galabovaa Apr 30, 2025
33e62af
highs-mip-worker-2 merge
galabovaa Apr 30, 2025
1bf4195
clear temporary files
galabovaa Apr 30, 2025
154747b
formatting
galabovaa Apr 30, 2025
440915a
highsmipworker warning constructor order macos
galabovaa Apr 30, 2025
5b5d3d7
temporarily disable workflows for windows and macos, add HighsMipWork…
galabovaa Apr 30, 2025
cea0d6b
disabled callback test highs-callback-mip-user-solution
galabovaa Apr 30, 2025
42293e5
disabled multiobjective and two failing mipsolver tests
galabovaa Apr 30, 2025
36280f6
tweaks to get to a working state for all tests
galabovaa May 1, 2025
d2a654f
lseu debug64 passing, heuristics during the dive switched off
galabovaa May 2, 2025
391e477
formatting and comments
galabovaa May 2, 2025
0a1623c
added methods to store incumbent solution
galabovaa May 5, 2025
5b7e8e0
formatting
galabovaa May 5, 2025
6d77072
move worker init outside of search loopgit add --all
galabovaa May 5, 2025
3e700fe
formatting
galabovaa May 5, 2025
e9d5c6c
Introduced mip_search_concurrency option
jajhall May 20, 2025
5479e92
Added check that there is exactly one node on the queue to start with
jajhall May 21, 2025
74be9c7
Added data members for parallel search to HighsSearch.h and lambdas t…
jajhall May 21, 2025
9d6291b
Add missing milp changes
Opt-Mucca Sep 4, 2025
353896d
Add search_started flag
Opt-Mucca Sep 4, 2025
88e3eb2
Add master_worker.search as default
Opt-Mucca Sep 9, 2025
848ced1
Add thread safe undoPrimal option
Opt-Mucca Sep 11, 2025
59c8dd3
Add basic parallel lock
Opt-Mucca Sep 11, 2025
97ea40d
Add atomic check and delay aging for cuts
Opt-Mucca Sep 12, 2025
690063b
Update solution passing
Opt-Mucca Sep 12, 2025
f11e10a
Add conflict pool parallelism skeleton
Opt-Mucca Sep 15, 2025
963a7a1
GO back to stable state
Opt-Mucca Sep 16, 2025
ea5bdc3
Add domains dequeu
Opt-Mucca Sep 16, 2025
cc9a7eb
Use mipworker.globaldom_ in sepa
Opt-Mucca Sep 16, 2025
219f69e
cutgen now uses worker global domain
Opt-Mucca Sep 22, 2025
e5d29b8
Use globaldom for redcosts (not root)
Opt-Mucca Sep 22, 2025
05cc5ec
Add globaldom to all heuristics
Opt-Mucca Sep 22, 2025
d580c4d
Add index to lprow for cutpool
Opt-Mucca Sep 22, 2025
ec1c4cc
Add pointer magic for cutpool during shrink
Opt-Mucca Sep 22, 2025
05c430e
Pass globaldom to some lprelaxation functions
Opt-Mucca Sep 22, 2025
6ec6465
Replace more global domain usages
Opt-Mucca Sep 23, 2025
2f5ddc5
Give all lp relaxations a index
Opt-Mucca Sep 23, 2025
1263d08
Add globaldom to implications
Opt-Mucca Sep 23, 2025
d45d294
Add globaldom as arg to conflictanalysis
Opt-Mucca Sep 23, 2025
7f946c5
Pass local conflict pool to redcost propagation
Opt-Mucca Sep 23, 2025
a9a9476
Make lpcutremoved thread safe
Opt-Mucca Sep 23, 2025
8a96182
Access lprelax in heur via worker
Opt-Mucca Sep 24, 2025
0e80ead
Make cutpool a pointer
Opt-Mucca Sep 24, 2025
9345801
Make lprelax also pointer. Add convencience functions
Opt-Mucca Sep 24, 2025
1aaf5da
Add more lambda functions
Opt-Mucca Sep 24, 2025
3a575ec
Fix bug on non-synced solutions
Opt-Mucca Sep 24, 2025
4d322af
Add more lambdas. Start work on main loop
Opt-Mucca Sep 25, 2025
f79b79c
Create lambda for evaluating nodes
Opt-Mucca Sep 25, 2025
b8bf59f
Create lambda for handling pruned nodes
Opt-Mucca Sep 25, 2025
ebec009
Use sepa per worker
Opt-Mucca Sep 25, 2025
d171a40
Add lambda for sepa and store basis
Opt-Mucca Sep 25, 2025
b0b8374
Use mipworker cutpool in separation
Opt-Mucca Sep 26, 2025
b1f1acc
Add parallel lock. Fix cut pool sepa
Opt-Mucca Sep 26, 2025
75b7e7b
Increase numlps when copying an LP
Opt-Mucca Sep 29, 2025
092ea99
Rework locks. Add missing lower bound update
Opt-Mucca Sep 29, 2025
d9c57a6
Add more solution syncs. Fix wrong index and addincumbent call
Opt-Mucca Sep 29, 2025
62c4994
Add sync pools
Opt-Mucca Sep 30, 2025
a4ac096
Fix conflict bug. Parallel dives
Opt-Mucca Sep 30, 2025
c4cf00b
Add heuristics to dive
Opt-Mucca Sep 30, 2025
7879c0e
Add missing lock
Opt-Mucca Oct 1, 2025
1da3cdf
Add global cutpool aging. Add safe local pool aging
Opt-Mucca Oct 1, 2025
2e6aba5
Allow implied bounds sepa parallel
Opt-Mucca Oct 1, 2025
c59322a
general worker create lambda. Make conflictpool a pointer
Opt-Mucca Oct 1, 2025
0408d10
use local conflict pool and worker sols in heur
Opt-Mucca Oct 1, 2025
5d07616
Make helper functions for flushing global domain changes
Opt-Mucca Oct 2, 2025
94b909b
Make globaldom_ a pointer too
Opt-Mucca Oct 2, 2025
892d098
Add miptwork to lp. Fix some global info updates
Opt-Mucca Oct 2, 2025
1d8882e
Make master worker use local global copy
Opt-Mucca Oct 2, 2025
a53e0da
Remove debugging resize
Opt-Mucca Oct 2, 2025
9d0eee8
Correctly add incumbent to worker or global
Opt-Mucca Oct 2, 2025
917d61f
Fix worker solution. Add more checks
Opt-Mucca Oct 6, 2025
f1ea4bf
Add more calls to worker in lprelax
Opt-Mucca Oct 6, 2025
5065984
Fix incorrect logic
Opt-Mucca Oct 6, 2025
7ee9606
Add cut aging call
Opt-Mucca Oct 6, 2025
e3ee17c
Disable broken aging
Opt-Mucca Oct 6, 2025
fd13d2f
Remove redundant line. Fix order of calls
Opt-Mucca Oct 7, 2025
756d7cf
Rework how cutspools are handled in paralell case
Opt-Mucca Dec 1, 2025
34145f9
Add minor changes on when stuff is called
Opt-Mucca Dec 2, 2025
f97964c
Age the local cut pools
Opt-Mucca Dec 2, 2025
cf8dc44
re-enable test and fix cut aging
Opt-Mucca Dec 2, 2025
7bb891b
Reenable more tests
Opt-Mucca Dec 2, 2025
05c83ea
Merge v1.12 into branch"
Opt-Mucca Dec 3, 2025
cfc2795
Add highdebugsol. Add simulate_concurrency option
Opt-Mucca Dec 3, 2025
341b2c9
Disable heuristic timers when parallel lock is active
Opt-Mucca Dec 18, 2025
d828de6
Fix minor bugs. Comment out confusing code"
Opt-Mucca Dec 19, 2025
58d05c3
Remove unnecessary debug solution resetdomains
Opt-Mucca Dec 19, 2025
8f6489c
Fix minor things. Add comments
Opt-Mucca Jan 5, 2026
ef918f3
Add generalised parallel call
Opt-Mucca Jan 5, 2026
66b4f3d
Parallelise dive and separate functions
Opt-Mucca Jan 6, 2026
701a8e7
Fix clocks. Enable heuristics
Opt-Mucca Jan 6, 2026
257bacd
Disable parallelism for submips. Add missing search domain sync
Opt-Mucca Jan 6, 2026
1ae4665
Add C++ LLM black magic
Opt-Mucca Jan 7, 2026
895e6a8
sync and flush functions for local pseudocosts
Opt-Mucca Jan 8, 2026
16f34e6
Add pseudo-cost deque to mipsolverdata
Opt-Mucca Jan 8, 2026
8f7d267
Make pseudo-costs not be optimized out
Opt-Mucca Jan 8, 2026
bcfa281
Enable clique seperation for parallel
Opt-Mucca Jan 9, 2026
aa58e8c
Fix incorrect logic
Opt-Mucca Jan 9, 2026
52efade
Correctly handle infeasible return via updateActivity in cutpoolprop
Opt-Mucca Jan 9, 2026
935cca1
Make compiler happy with highsint"
Opt-Mucca Jan 9, 2026
dc2d1ea
Rename and tidy up
Opt-Mucca Jan 12, 2026
8bfb9fc
Parallelise and sync reset worker domains
Opt-Mucca Jan 13, 2026
4f5b4cf
More tidying up
Opt-Mucca Jan 13, 2026
a4777bd
Tidy up. Revert incorrect simplification
Opt-Mucca Jan 13, 2026
5af1a62
Create sepa stats
Opt-Mucca Jan 13, 2026
c4ee39e
Add duplicate check in master cut pool
Opt-Mucca Jan 13, 2026
9ae2cda
Remove reference re-assignment attempts
Opt-Mucca Jan 14, 2026
f5e1014
Tidy up LpRelaxation functions
Opt-Mucca Jan 14, 2026
6174a83
Clean up heuristic stats
Opt-Mucca Jan 14, 2026
6887c5e
Add terminator calls using worker info
Opt-Mucca Jan 14, 2026
976c023
Update worker upper bound in single-threaded case
Opt-Mucca Jan 14, 2026
9a1bc7e
Add general addincumbent and trySoolution functions to heursitics"
Opt-Mucca Jan 14, 2026
febe041
Clean up HighsSearch
Opt-Mucca Jan 14, 2026
f73c828
Tidy up separators
Opt-Mucca Jan 14, 2026
d578ee8
Rename usedInDive and usedInROund
Opt-Mucca Jan 15, 2026
0f309d6
Tidy up HighsMipSolver
Opt-Mucca Jan 15, 2026
cc21b5f
Enable trivial heur. Change sync sol logic.
Opt-Mucca Jan 15, 2026
31ee713
Reenable RENS at root. Tidy up HighsMipSolverData
Opt-Mucca Jan 15, 2026
e501353
Reenable root reduced cost heuristic
Opt-Mucca Jan 16, 2026
62ce4b8
Add getter functions for global + worker heur stats
Opt-Mucca Jan 16, 2026
ada97eb
Use original random seed when not in parallel
Opt-Mucca Jan 16, 2026
b67fce8
Dont sync ps in single worker case
Opt-Mucca Jan 16, 2026
fc77312
Update global pseudo cost is lock not active
Opt-Mucca Jan 19, 2026
f2b2c81
Fix bug with intcols being globally changes
Opt-Mucca Jan 19, 2026
5d54551
Fix error in conflict score averaging
Opt-Mucca Jan 19, 2026
15d217f
Remove conflict weight multiplier
Opt-Mucca Jan 20, 2026
8261ee6
Reset sepa inbetween restarts
Opt-Mucca Jan 20, 2026
a2cf2ff
Add centralised backtrack plunge
Opt-Mucca Jan 20, 2026
ded9f80
Initialise numCol in worker nodequeue. Fix index bug
Opt-Mucca Jan 20, 2026
00aa78d
Scale backtrack plunge budget by workers
Opt-Mucca Jan 21, 2026
c4fbbb6
Fix bugs. Re-enable compiler optimisation
Opt-Mucca Jan 21, 2026
6a7a45b
Enable bazel sanitizers
Opt-Mucca Jan 21, 2026
9fbd004
reverse order of domain and pools
Opt-Mucca Jan 21, 2026
4ab615a
Change order of members
Opt-Mucca Jan 21, 2026
fb2269b
Comment out an LP timer
Opt-Mucca Jan 21, 2026
6063638
Change backtracked to uint8_t too
Opt-Mucca Jan 22, 2026
4eaf31e
Dont check limits during search if parallel
Opt-Mucca Jan 22, 2026
5a0e839
Define shared pointer to basis inside of lambda
Opt-Mucca Jan 22, 2026
bc26bb7
Introduce new serial parameter to runTask
Opt-Mucca Jan 22, 2026
62911e8
Add safety rail to copying poolprops
Opt-Mucca Jan 22, 2026
9f8dc9f
Add parallel.md for help in understading branch
Opt-Mucca Jan 23, 2026
be7655c
Add extra TODO to parallel.md
Opt-Mucca Jan 23, 2026
89684d9
Dynamically create workers
Opt-Mucca Jan 29, 2026
48f8bf9
Change code to avoid confusion on domain resetting
Opt-Mucca Jan 30, 2026
f423df7
Remove point from parallel.md. Make bazel happy with parallel
Opt-Mucca Jan 30, 2026
98c7564
Fix bug of skipping infeasible row activity update
Opt-Mucca Feb 2, 2026
4e29a0d
Add an extra solution sync
Opt-Mucca Feb 3, 2026
6aef65f
Merge latest into branch
Opt-Mucca Mar 2, 2026
f0c99ec
Github action stuff
Opt-Mucca Mar 2, 2026
f6afc95
github action v2
Opt-Mucca Mar 2, 2026
a654d5d
Reformat after merging latest
Opt-Mucca Mar 2, 2026
56b8567
Add comments from Franz
Opt-Mucca Mar 3, 2026
24a3726
Comments from Franz v2
Opt-Mucca Mar 3, 2026
08ad869
Remove forward declaration and potential circualr dependency
Opt-Mucca Mar 3, 2026
a06cf54
Formatting
Opt-Mucca Mar 3, 2026
9314a91
Remove empty line
Opt-Mucca Mar 4, 2026
832ebd8
Comments from Franz v3
Opt-Mucca Mar 4, 2026
9863be4
Move assert outside loop
Opt-Mucca Mar 5, 2026
f28a935
Make globaldom const in translp
Opt-Mucca Mar 13, 2026
9bedd5a
Merge branch 'latest' into hmw-mt
jajhall Mar 15, 2026
93b6992
Fix cutpool aging bugs. Enable MIP timers in non-parallel
Opt-Mucca Mar 16, 2026
1e6813a
Double backtrack plunge allowance
Opt-Mucca Mar 16, 2026
eaae314
Add deterministic test
Opt-Mucca Mar 16, 2026
0e069b0
Make thread sanitizer happy
Opt-Mucca Mar 17, 2026
d2c4528
Remove references
fwesselm Mar 17, 2026
1637356
Revert std::atomic for parallel_lock
Opt-Mucca Mar 17, 2026
bdba2bd
Format. Fix pseudocost bug. Move cutpool init
Opt-Mucca Mar 17, 2026
5f85038
Add HighsMipWorker.cpp to meson.build"
Opt-Mucca Mar 17, 2026
8d81865
Add const getter functions
Opt-Mucca Mar 17, 2026
323a03f
Merge branch 'hmw-mt-2' into hmw-mt
Opt-Mucca Mar 17, 2026
7a2cbe4
Refactor main solve loop. Create single sync point
Opt-Mucca Mar 25, 2026
57ab48e
Fix bugs in refactor.
Opt-Mucca Mar 25, 2026
99092ad
Make additional check for diff solution path
Opt-Mucca Mar 25, 2026
be54b11
Separate worker cutpools. Keep dyanmic worker spawning
Opt-Mucca Mar 25, 2026
16d9bd1
Make formatter happy
Opt-Mucca Mar 25, 2026
9c94db2
Delete pools after highsmipworker. Check if valgrind is happy
Opt-Mucca Mar 26, 2026
114e23c
Also sync propagated cuts. Disable heuristics during rampup
Opt-Mucca Mar 27, 2026
7ad0e81
Randomise heuristic allowance for workers
Opt-Mucca Mar 27, 2026
079c4b1
Move basis re-init to correct location
Opt-Mucca Mar 27, 2026
55818e8
Destroy old workers after resetting sepa / search for masterworker
Opt-Mucca Mar 27, 2026
bb7104f
Make std::max happy with two HighsInts
Opt-Mucca Mar 31, 2026
5ee6fdb
Merge branch 'latest' into hmw-mt
fwesselm Apr 7, 2026
df8d8a1
Fix merge issue
fwesselm Apr 7, 2026
dc108e6
Remove extra semicolon
fwesselm Apr 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions check/TestCheckSolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ TEST_CASE("check-set-mip-solution", "[highs_check_solution]") {
HighsSolution optimal_solution = highs.getSolution();

HighsInt scratch_num_nodes = info.mip_node_count;
HighsInt scratch_num_simplex = info.simplex_iteration_count;
if (dev_run) printf("Num nodes = %d\n", int(scratch_num_nodes));

std::string solution_file = test_name + model + ".sol";
Expand All @@ -113,7 +114,9 @@ TEST_CASE("check-set-mip-solution", "[highs_check_solution]") {

highs.run();
if (dev_run) printf("Num nodes = %d\n", int(info.mip_node_count));
REQUIRE(info.mip_node_count != scratch_num_nodes);
const bool different_search = info.mip_node_count != scratch_num_nodes ||
info.simplex_iteration_count != scratch_num_simplex;
REQUIRE(different_search);
highs.clear();
}

Expand All @@ -132,7 +135,9 @@ TEST_CASE("check-set-mip-solution", "[highs_check_solution]") {

highs.run();
if (dev_run) printf("Num nodes = %d\n", int(info.mip_node_count));
REQUIRE(info.mip_node_count != scratch_num_nodes);
const bool different_search = info.mip_node_count != scratch_num_nodes ||
info.simplex_iteration_count != scratch_num_simplex;
REQUIRE(different_search);
highs.clear();
}

Expand Down Expand Up @@ -162,7 +167,9 @@ TEST_CASE("check-set-mip-solution", "[highs_check_solution]") {

highs.run();
if (dev_run) printf("Num nodes = %d\n", int(info.mip_node_count));
REQUIRE(info.mip_node_count != scratch_num_nodes);
const bool different_search = info.mip_node_count != scratch_num_nodes ||
info.simplex_iteration_count != scratch_num_simplex;
REQUIRE(different_search);
highs.clear();
}

Expand All @@ -185,7 +192,9 @@ TEST_CASE("check-set-mip-solution", "[highs_check_solution]") {

highs.run();
if (dev_run) printf("Num nodes = %d\n", int(info.mip_node_count));
REQUIRE(info.mip_node_count != scratch_num_nodes);
const bool different_search = info.mip_node_count != scratch_num_nodes ||
info.simplex_iteration_count != scratch_num_simplex;
REQUIRE(different_search);
highs.clear();
}

Expand Down Expand Up @@ -232,7 +241,9 @@ TEST_CASE("check-set-mip-solution", "[highs_check_solution]") {
return_status = highs.setSolution(starting_solution);
REQUIRE(return_status == HighsStatus::kOk);
highs.run();
REQUIRE(info.mip_node_count != scratch_num_nodes);
const bool different_search = info.mip_node_count != scratch_num_nodes ||
info.simplex_iteration_count != scratch_num_simplex;
REQUIRE(different_search);
highs.clear();
}

Expand Down Expand Up @@ -283,7 +294,9 @@ TEST_CASE("check-set-mip-solution", "[highs_check_solution]") {
return_status = highs.setSolution(num_entries, index.data(), value.data());
REQUIRE(return_status == HighsStatus::kOk);
highs.run();
REQUIRE(info.mip_node_count != scratch_num_nodes);
const bool different_search = info.mip_node_count != scratch_num_nodes ||
info.simplex_iteration_count != scratch_num_simplex;
REQUIRE(different_search);
highs.clear();
}
assert(other_tests);
Expand Down
22 changes: 22 additions & 0 deletions check/TestMipSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1404,3 +1404,25 @@ TEST_CASE("issue-2173", "[highs_test_mip_solver]") {
const double optimal_objective = -26770.8075489;
solve(highs, kHighsOnString, require_model_status, optimal_objective);
}

TEST_CASE("parallel-mip-determinism", "[highs_test_mip_solver]") {
std::string filename = std::string(HIGHS_DIR) + "/check/instances/bell5.mps";
HighsInt num_runs = 6;
std::vector<HighsInt> lp_iters(num_runs);
for (HighsInt i = 0; i < num_runs; i++) {
Highs highs;
highs.setOptionValue("output_flag", dev_run);
highs.setOptionValue("mip_rel_gap", 0);
highs.setOptionValue("threads", 2);
highs.setOptionValue("mip_search_concurrency", 2);
if (i % 2 == 0) highs.setOptionValue("mip_search_simulate_concurrency", 1);
highs.readModel(filename);
const HighsModelStatus require_model_status = HighsModelStatus::kOptimal;
const double optimal_objective = 8966406.491519;
solve(highs, kHighsOffString, require_model_status, optimal_objective);
lp_iters[i] = highs.getInfo().simplex_iteration_count;
if (i > 0) {
REQUIRE(lp_iters[i] == lp_iters[0]);
}
}
}
2 changes: 2 additions & 0 deletions cmake/sources-python.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ set(highs_sources_python
highs/mip/HighsMipAnalysis.cpp
highs/mip/HighsMipSolver.cpp
highs/mip/HighsMipSolverData.cpp
highs/mip/HighsMipWorker.cpp
highs/mip/HighsModkSeparator.cpp
highs/mip/HighsNodeQueue.cpp
highs/mip/HighsObjectiveFunction.cpp
Expand Down Expand Up @@ -342,6 +343,7 @@ set(highs_headers_python
highs/mip/HighsMipAnalysis.h
highs/mip/HighsMipSolver.h
highs/mip/HighsMipSolverData.h
highs/mip/HighsMipWorker.h
highs/mip/HighsModkSeparator.h
highs/mip/HighsNodeQueue.h
highs/mip/HighsObjectiveFunction.h
Expand Down
2 changes: 2 additions & 0 deletions cmake/sources.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ set(highs_sources
mip/HighsMipAnalysis.cpp
mip/HighsMipSolver.cpp
mip/HighsMipSolverData.cpp
mip/HighsMipWorker.cpp
mip/HighsModkSeparator.cpp
mip/HighsNodeQueue.cpp
mip/HighsObjectiveFunction.cpp
Expand Down Expand Up @@ -499,6 +500,7 @@ set(highs_headers
mip/HighsMipAnalysis.h
mip/HighsMipSolver.h
mip/HighsMipSolverData.h
mip/HighsMipWorker.h
mip/HighsModkSeparator.h
mip/HighsNodeQueue.h
mip/HighsObjectiveFunction.h
Expand Down
1 change: 1 addition & 0 deletions highs/lp_data/HConst.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const std::string kHighsChooseString = "choose";
const std::string kHighsOnString = "on";
const HighsInt kHighsMaxStringLength = 512;
const HighsInt kSimplexConcurrencyLimit = 8;
const HighsInt kMipSearchConcurrencyLimit = 8;
const double kRunningAverageMultiplier = 0.05;

const double kExcessivelySmallObjectiveCoefficient = 1e-4;
Expand Down
16 changes: 16 additions & 0 deletions highs/lp_data/HighsOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,8 @@ struct HighsOptionsStruct {
std::string mip_improving_solution_file;
bool mip_root_presolve_only;
HighsInt mip_lifting_for_probing;
HighsInt mip_search_concurrency;
bool mip_search_simulate_concurrency;
bool mip_allow_cut_separation_at_nodes;

// Logging callback identifiers
Expand Down Expand Up @@ -667,6 +669,8 @@ struct HighsOptionsStruct {
mip_improving_solution_file(""),
mip_root_presolve_only(false),
mip_lifting_for_probing(-1),
mip_search_concurrency(0),
mip_search_simulate_concurrency(false),
// clang-format off
mip_allow_cut_separation_at_nodes(true) {};
// clang-format on
Expand Down Expand Up @@ -1284,6 +1288,18 @@ class HighsOptions : public HighsOptionsStruct {
kHighsInf);
records.push_back(record_double);

record_int = new OptionRecordInt(
"mip_search_concurrency",
"Number of workers to create per thread for concurrent MIP search",
advanced, &mip_search_concurrency, 0, 2, kMipSearchConcurrencyLimit);
records.push_back(record_int);

record_bool = new OptionRecordBool(
"mip_search_simulate_concurrency",
"Simulate MIP search concurrency on a single thread", advanced,
&mip_search_simulate_concurrency, false);
records.push_back(record_bool);

record_int = new OptionRecordInt(
"ipm_iteration_limit", "Iteration limit for IPM solver", advanced,
&ipm_iteration_limit, 0, kHighsIInf, kHighsIInf);
Expand Down
1 change: 1 addition & 0 deletions highs/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ _srcs = [
'mip/HighsMipAnalysis.cpp',
'mip/HighsMipSolver.cpp',
'mip/HighsMipSolverData.cpp',
'mip/HighsMipWorker.cpp',
'mip/HighsModkSeparator.cpp',
'mip/HighsNodeQueue.cpp',
'mip/HighsObjectiveFunction.cpp',
Expand Down
24 changes: 13 additions & 11 deletions highs/mip/HighsCliqueTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@ bool HighsCliqueTable::processNewEdge(HighsDomain& globaldom, CliqueVar v1,
void HighsCliqueTable::addClique(const HighsMipSolver& mipsolver,
CliqueVar* cliquevars, HighsInt numcliquevars,
bool equality, HighsInt origin) {
HighsDomain& globaldom = mipsolver.mipdata_->domain;
HighsDomain& globaldom = mipsolver.mipdata_->getDomain();
mipsolver.mipdata_->debugSolution.checkClique(cliquevars, numcliquevars);
const HighsInt maxNumCliqueVars = 100;

Expand Down Expand Up @@ -841,7 +841,7 @@ void HighsCliqueTable::extractCliques(
HighsInt nbin, std::vector<HighsInt>& perm, std::vector<CliqueVar>& clique,
double feastol) {
HighsImplications& implics = mipsolver.mipdata_->implications;
HighsDomain& globaldom = mipsolver.mipdata_->domain;
HighsDomain& globaldom = mipsolver.mipdata_->getDomain();

perm.resize(inds.size());
std::iota(perm.begin(), perm.end(), 0);
Expand Down Expand Up @@ -1081,7 +1081,7 @@ void HighsCliqueTable::extractCliquesFromCut(const HighsMipSolver& mipsolver,
if (isFull()) return;

HighsImplications& implics = mipsolver.mipdata_->implications;
HighsDomain& globaldom = mipsolver.mipdata_->domain;
HighsDomain& globaldom = mipsolver.mipdata_->getDomain();

const double feastol = mipsolver.mipdata_->feastol;

Expand Down Expand Up @@ -1276,7 +1276,7 @@ void HighsCliqueTable::extractCliques(HighsMipSolver& mipsolver,

double rhs;

HighsDomain& globaldom = mipsolver.mipdata_->domain;
HighsDomain& globaldom = mipsolver.mipdata_->getDomain();

for (HighsInt i = 0; i != mipsolver.numRow(); ++i) {
HighsInt start = mipsolver.mipdata_->ARstart_[i];
Expand Down Expand Up @@ -1380,7 +1380,7 @@ void HighsCliqueTable::extractObjCliques(HighsMipSolver& mipsolver) {
HighsInt nbin =
mipsolver.mipdata_->objectiveFunction.getNumBinariesInObjective();
if (nbin <= 1) return;
HighsDomain& globaldom = mipsolver.mipdata_->domain;
HighsDomain& globaldom = mipsolver.mipdata_->getDomain();
if (globaldom.getObjectiveLowerBound() == -kHighsInf) return;

const double* vals;
Expand Down Expand Up @@ -1603,15 +1603,17 @@ void HighsCliqueTable::vertexInfeasible(HighsDomain& globaldom, HighsInt col,

void HighsCliqueTable::separateCliques(const HighsMipSolver& mipsolver,
const std::vector<double>& sol,
HighsCutPool& cutpool, double feastol) {
HighsCutPool& cutpool, double feastol,
HighsRandom& randgen,
int64_t& localNumNeighbourhoodQueries) {
BronKerboschData data(sol);
data.feastol = feastol;
data.maxNeighbourhoodQueries = 1000000 +
int64_t{100} * mipsolver.numNonzero() +
mipsolver.mipdata_->total_lp_iterations * 1000;
if (numNeighbourhoodQueries > data.maxNeighbourhoodQueries) return;
data.maxNeighbourhoodQueries -= numNeighbourhoodQueries;
const HighsDomain& globaldom = mipsolver.mipdata_->domain;
const HighsDomain& globaldom = mipsolver.mipdata_->getDomain();

for (HighsInt i : mipsolver.mipdata_->integral_cols) {
if (colsubstituted[i] || colDeleted[i]) continue;
Expand Down Expand Up @@ -1698,9 +1700,9 @@ void HighsCliqueTable::separateCliques(const HighsMipSolver& mipsolver,
false, false);
}

numNeighbourhoodQueries += data.numNeighbourhoodQueries;
localNumNeighbourhoodQueries += data.numNeighbourhoodQueries;

if (runcliquesubsumption) {
if (runcliquesubsumption && &randgen == &this->randgen) {
for (std::vector<CliqueVar>& clique : data.cliques) {
HighsInt nremoved = runCliqueSubsumption(globaldom, clique);

Expand Down Expand Up @@ -1841,7 +1843,7 @@ void HighsCliqueTable::cleanupFixed(HighsDomain& globaldom) {
if (nfixings != oldnfixings) propagateAndCleanup(globaldom);
}

HighsInt HighsCliqueTable::getNumImplications(HighsInt col) {
HighsInt HighsCliqueTable::getNumImplications(HighsInt col) const {
// first count all cliques as one implication, so that cliques of size two
// are accounted for already
HighsInt i0 = CliqueVar(col, 0).index();
Expand All @@ -1860,7 +1862,7 @@ HighsInt HighsCliqueTable::getNumImplications(HighsInt col) {
return numimplics;
}

HighsInt HighsCliqueTable::getNumImplications(HighsInt col, bool val) {
HighsInt HighsCliqueTable::getNumImplications(HighsInt col, bool val) const {
HighsInt iVal = CliqueVar(col, val).index();

// each size two clique is one implication
Expand Down
11 changes: 8 additions & 3 deletions highs/mip/HighsCliqueTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ class HighsCliqueTable {

HighsInt getNumEntries() const { return numEntries; }

HighsRandom& getRandgen() { return randgen; }

int64_t& getNumNeighbourhoodQueries() { return numNeighbourhoodQueries; }

HighsInt partitionNeighbourhood(std::vector<HighsInt>& neighbourhoodInds,
int64_t& numNeighbourhoodqueries, CliqueVar v,
CliqueVar* q, HighsInt N) const;
Expand Down Expand Up @@ -287,7 +291,8 @@ class HighsCliqueTable {

void separateCliques(const HighsMipSolver& mipsolver,
const std::vector<double>& sol, HighsCutPool& cutpool,
double feastol);
double feastol, HighsRandom& randgen,
int64_t& localNumNeighbourhoodQueries);

std::vector<std::vector<CliqueVar>> separateCliques(
const std::vector<double>& sol, const HighsDomain& globaldom,
Expand All @@ -300,9 +305,9 @@ class HighsCliqueTable {

void addImplications(HighsDomain& domain, HighsInt col, HighsInt val);

HighsInt getNumImplications(HighsInt col);
HighsInt getNumImplications(HighsInt col) const;

HighsInt getNumImplications(HighsInt col, bool val);
HighsInt getNumImplications(HighsInt col, bool val) const;

void runCliqueMerging(HighsDomain& globaldomain);

Expand Down
Loading
Loading