25
25
#include < optional>
26
26
#include < random>
27
27
#include < string>
28
+ #include < string_view>
28
29
#include < thread>
29
30
#include < utility>
30
31
#include < vector>
46
47
#include " absl/strings/str_format.h"
47
48
#include " absl/strings/str_join.h"
48
49
#include " absl/strings/string_view.h"
50
+ #include " absl/strings/strip.h"
49
51
#include " absl/synchronization/mutex.h"
50
52
#include " absl/types/span.h"
51
53
#include " google/protobuf/arena.h"
@@ -1293,14 +1295,14 @@ class FeasibilityPumpSolver : public SubSolver {
1293
1295
class LnsSolver : public SubSolver {
1294
1296
public:
1295
1297
LnsSolver (std::unique_ptr<NeighborhoodGenerator> generator,
1296
- const SatParameters& lns_parameters ,
1297
- NeighborhoodGeneratorHelper* helper, SharedClasses* shared ,
1298
- int preferred_linearization_level = 0 )
1298
+ const SatParameters& lns_parameters_base ,
1299
+ const SatParameters& lns_parameters_stalling ,
1300
+ NeighborhoodGeneratorHelper* helper, SharedClasses* shared )
1299
1301
: SubSolver(generator->name (), INCOMPLETE),
1300
- preferred_linearization_level_(preferred_linearization_level),
1301
1302
generator_(std::move(generator)),
1302
1303
helper_(helper),
1303
- lns_parameters_(lns_parameters),
1304
+ lns_parameters_base_(lns_parameters_base),
1305
+ lns_parameters_stalling_(lns_parameters_stalling),
1304
1306
shared_(shared) {}
1305
1307
1306
1308
~LnsSolver () override {
@@ -1328,7 +1330,7 @@ class LnsSolver : public SubSolver {
1328
1330
// change the LNS behavior.
1329
1331
const int32_t low = static_cast <int32_t >(task_id);
1330
1332
const int32_t high = static_cast <int32_t >(task_id >> 32 );
1331
- std::seed_seq seed{low, high, lns_parameters_ .random_seed ()};
1333
+ std::seed_seq seed{low, high, lns_parameters_base_ .random_seed ()};
1332
1334
random_engine_t random (seed);
1333
1335
1334
1336
NeighborhoodGenerator::SolveData data;
@@ -1372,26 +1374,22 @@ class LnsSolver : public SubSolver {
1372
1374
1373
1375
if (!neighborhood.is_generated ) return ;
1374
1376
1375
- SatParameters local_params (lns_parameters_);
1376
- local_params.set_max_deterministic_time (data.deterministic_limit );
1377
+ SatParameters local_params;
1377
1378
1378
- // TODO(user): Tune these.
1379
1379
// TODO(user): This could be a good candidate for bandits.
1380
1380
const int64_t stall = generator_->num_consecutive_non_improving_calls ();
1381
- std::string search_info;
1382
1381
const int search_index = stall < 10 ? 0 : task_id % 2 ;
1383
1382
switch (search_index) {
1384
1383
case 0 :
1385
- local_params.set_search_branching (SatParameters::AUTOMATIC_SEARCH);
1386
- local_params.set_linearization_level (preferred_linearization_level_);
1387
- search_info = absl::StrCat (" auto_l" , preferred_linearization_level_);
1384
+ local_params = lns_parameters_base_;
1388
1385
break ;
1389
1386
default :
1390
- local_params.set_search_branching (SatParameters::PORTFOLIO_SEARCH);
1391
- local_params.set_search_random_variable_pool_size (5 );
1392
- search_info = " folio_rnd" ;
1387
+ local_params = lns_parameters_stalling_;
1393
1388
break ;
1394
1389
}
1390
+ const std::string_view search_info =
1391
+ absl::StripPrefix (std::string_view (local_params.name ()), " lns_" );
1392
+ local_params.set_max_deterministic_time (data.deterministic_limit );
1395
1393
1396
1394
std::string source_info =
1397
1395
neighborhood.source_info .empty () ? name () : neighborhood.source_info ;
@@ -1486,7 +1484,7 @@ class LnsSolver : public SubSolver {
1486
1484
}
1487
1485
}
1488
1486
bool hint_feasible_before_presolve = false ;
1489
- if (lns_parameters_ .debug_crash_if_presolve_breaks_hint ()) {
1487
+ if (lns_parameters_base_ .debug_crash_if_presolve_breaks_hint ()) {
1490
1488
hint_feasible_before_presolve =
1491
1489
SolutionHintIsCompleteAndFeasible (lns_fragment, /* logger=*/ nullptr );
1492
1490
}
@@ -1525,7 +1523,7 @@ class LnsSolver : public SubSolver {
1525
1523
context.reset (nullptr );
1526
1524
neighborhood.delta .Clear ();
1527
1525
1528
- if (lns_parameters_ .debug_crash_if_presolve_breaks_hint () &&
1526
+ if (lns_parameters_base_ .debug_crash_if_presolve_breaks_hint () &&
1529
1527
hint_feasible_before_presolve &&
1530
1528
!SolutionHintIsCompleteAndFeasible (lns_fragment,
1531
1529
/* logger=*/ nullptr )) {
@@ -1720,10 +1718,10 @@ class LnsSolver : public SubSolver {
1720
1718
}
1721
1719
1722
1720
private:
1723
- int preferred_linearization_level_ = 0 ;
1724
1721
std::unique_ptr<NeighborhoodGenerator> generator_;
1725
1722
NeighborhoodGeneratorHelper* helper_;
1726
- const SatParameters lns_parameters_;
1723
+ const SatParameters lns_parameters_base_;
1724
+ const SatParameters lns_parameters_stalling_;
1727
1725
SharedClasses* shared_;
1728
1726
// This is a optimization to allocate the arena for the LNS fragment already
1729
1727
// at roughly the right size. We will update it with the last size of the
@@ -1780,7 +1778,9 @@ void SolveCpModelParallel(SharedClasses* shared, Model* global_model) {
1780
1778
}));
1781
1779
1782
1780
const auto name_to_params = GetNamedParameters (params);
1783
- const SatParameters& lns_params = name_to_params.at (" lns" );
1781
+ const SatParameters& lns_params_base = name_to_params.at (" lns_base" );
1782
+ const SatParameters& lns_params_stalling = name_to_params.at (" lns_stalling" );
1783
+ const SatParameters& lns_params_routing = name_to_params.at (" lns_routing" );
1784
1784
1785
1785
// Add the NeighborhoodGeneratorHelper as a special subsolver so that its
1786
1786
// Synchronize() is called before any LNS neighborhood solvers.
@@ -1854,7 +1854,7 @@ void SolveCpModelParallel(SharedClasses* shared, Model* global_model) {
1854
1854
std::make_unique<RelaxationInducedNeighborhoodGenerator>(
1855
1855
helper, shared->response , shared->lp_solutions .get (),
1856
1856
shared->incomplete_solutions .get (), name_filter.LastName ()),
1857
- lns_params , helper, shared));
1857
+ lns_params_base, lns_params_stalling , helper, shared));
1858
1858
}
1859
1859
1860
1860
// Add incomplete subsolvers that require an objective.
@@ -1870,45 +1870,45 @@ void SolveCpModelParallel(SharedClasses* shared, Model* global_model) {
1870
1870
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1871
1871
std::make_unique<RelaxRandomVariablesGenerator>(
1872
1872
helper, name_filter.LastName ()),
1873
- lns_params , helper, shared));
1873
+ lns_params_base, lns_params_stalling , helper, shared));
1874
1874
}
1875
1875
if (name_filter.Keep (" rnd_cst_lns" )) {
1876
1876
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1877
1877
std::make_unique<RelaxRandomConstraintsGenerator>(
1878
1878
helper, name_filter.LastName ()),
1879
- lns_params , helper, shared));
1879
+ lns_params_base, lns_params_stalling , helper, shared));
1880
1880
}
1881
1881
if (name_filter.Keep (" graph_var_lns" )) {
1882
1882
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1883
1883
std::make_unique<VariableGraphNeighborhoodGenerator>(
1884
1884
helper, name_filter.LastName ()),
1885
- lns_params , helper, shared));
1885
+ lns_params_base, lns_params_stalling , helper, shared));
1886
1886
}
1887
1887
if (name_filter.Keep (" graph_arc_lns" )) {
1888
1888
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1889
1889
std::make_unique<ArcGraphNeighborhoodGenerator>(
1890
1890
helper, name_filter.LastName ()),
1891
- lns_params , helper, shared));
1891
+ lns_params_base, lns_params_stalling , helper, shared));
1892
1892
}
1893
1893
if (name_filter.Keep (" graph_cst_lns" )) {
1894
1894
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1895
1895
std::make_unique<ConstraintGraphNeighborhoodGenerator>(
1896
1896
helper, name_filter.LastName ()),
1897
- lns_params , helper, shared));
1897
+ lns_params_base, lns_params_stalling , helper, shared));
1898
1898
}
1899
1899
if (name_filter.Keep (" graph_dec_lns" )) {
1900
1900
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1901
1901
std::make_unique<DecompositionGraphNeighborhoodGenerator>(
1902
1902
helper, name_filter.LastName ()),
1903
- lns_params , helper, shared));
1903
+ lns_params_base, lns_params_stalling , helper, shared));
1904
1904
}
1905
1905
if (params.use_lb_relax_lns () &&
1906
1906
params.num_workers () >= params.lb_relax_num_workers_threshold () &&
1907
1907
name_filter.Keep (" lb_relax_lns" )) {
1908
1908
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1909
1909
std::make_unique<LocalBranchingLpBasedNeighborhoodGenerator>(
1910
1910
helper, name_filter.LastName (), shared->time_limit , shared),
1911
- lns_params , helper, shared));
1911
+ lns_params_base, lns_params_stalling , helper, shared));
1912
1912
}
1913
1913
1914
1914
const bool has_no_overlap_or_cumulative =
@@ -1921,13 +1921,13 @@ void SolveCpModelParallel(SharedClasses* shared, Model* global_model) {
1921
1921
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1922
1922
std::make_unique<RandomIntervalSchedulingNeighborhoodGenerator>(
1923
1923
helper, name_filter.LastName ()),
1924
- lns_params , helper, shared));
1924
+ lns_params_base, lns_params_stalling , helper, shared));
1925
1925
}
1926
1926
if (name_filter.Keep (" scheduling_time_window_lns" )) {
1927
1927
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1928
1928
std::make_unique<SchedulingTimeWindowNeighborhoodGenerator>(
1929
1929
helper, name_filter.LastName ()),
1930
- lns_params , helper, shared));
1930
+ lns_params_base, lns_params_stalling , helper, shared));
1931
1931
}
1932
1932
const std::vector<std::vector<int >> intervals_in_constraints =
1933
1933
helper->GetUniqueIntervalSets ();
@@ -1936,7 +1936,7 @@ void SolveCpModelParallel(SharedClasses* shared, Model* global_model) {
1936
1936
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1937
1937
std::make_unique<SchedulingResourceWindowsNeighborhoodGenerator>(
1938
1938
helper, intervals_in_constraints, name_filter.LastName ()),
1939
- lns_params , helper, shared));
1939
+ lns_params_base, lns_params_stalling , helper, shared));
1940
1940
}
1941
1941
}
1942
1942
@@ -1948,31 +1948,31 @@ void SolveCpModelParallel(SharedClasses* shared, Model* global_model) {
1948
1948
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1949
1949
std::make_unique<RandomRectanglesPackingNeighborhoodGenerator>(
1950
1950
helper, name_filter.LastName ()),
1951
- lns_params , helper, shared));
1951
+ lns_params_base, lns_params_stalling , helper, shared));
1952
1952
}
1953
1953
if (name_filter.Keep (" packing_square_lns" )) {
1954
1954
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1955
1955
std::make_unique<RectanglesPackingRelaxOneNeighborhoodGenerator>(
1956
1956
helper, name_filter.LastName ()),
1957
- lns_params , helper, shared));
1957
+ lns_params_base, lns_params_stalling , helper, shared));
1958
1958
}
1959
1959
if (name_filter.Keep (" packing_swap_lns" )) {
1960
1960
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1961
1961
std::make_unique<RectanglesPackingRelaxTwoNeighborhoodsGenerator>(
1962
1962
helper, name_filter.LastName ()),
1963
- lns_params , helper, shared));
1963
+ lns_params_base, lns_params_stalling , helper, shared));
1964
1964
}
1965
1965
if (name_filter.Keep (" packing_precedences_lns" )) {
1966
1966
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1967
1967
std::make_unique<RandomPrecedencesPackingNeighborhoodGenerator>(
1968
1968
helper, name_filter.LastName ()),
1969
- lns_params , helper, shared));
1969
+ lns_params_base, lns_params_stalling , helper, shared));
1970
1970
}
1971
1971
if (name_filter.Keep (" packing_slice_lns" )) {
1972
1972
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1973
1973
std::make_unique<SlicePackingNeighborhoodGenerator>(
1974
1974
helper, name_filter.LastName ()),
1975
- lns_params , helper, shared));
1975
+ lns_params_base, lns_params_stalling , helper, shared));
1976
1976
}
1977
1977
}
1978
1978
@@ -1982,13 +1982,10 @@ void SolveCpModelParallel(SharedClasses* shared, Model* global_model) {
1982
1982
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1983
1983
std::make_unique<RandomPrecedenceSchedulingNeighborhoodGenerator>(
1984
1984
helper, name_filter.LastName ()),
1985
- lns_params , helper, shared));
1985
+ lns_params_base, lns_params_stalling , helper, shared));
1986
1986
}
1987
1987
}
1988
1988
1989
- // For routing, the LP relaxation seems pretty important, so we prefer an
1990
- // high linearization level to solve LNS subproblems.
1991
- const int routing_lin_level = 2 ;
1992
1989
const int num_circuit = static_cast <int >(
1993
1990
helper->TypeToConstraints (ConstraintProto::kCircuit ).size ());
1994
1991
const int num_routes = static_cast <int >(
@@ -1998,21 +1995,21 @@ void SolveCpModelParallel(SharedClasses* shared, Model* global_model) {
1998
1995
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
1999
1996
std::make_unique<RoutingRandomNeighborhoodGenerator>(
2000
1997
helper, name_filter.LastName ()),
2001
- lns_params, helper, shared, routing_lin_level ));
1998
+ lns_params_routing, lns_params_stalling, helper, shared ));
2002
1999
}
2003
2000
if (name_filter.Keep (" routing_path_lns" )) {
2004
2001
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
2005
2002
std::make_unique<RoutingPathNeighborhoodGenerator>(
2006
2003
helper, name_filter.LastName ()),
2007
- lns_params, helper, shared, routing_lin_level ));
2004
+ lns_params_routing, lns_params_stalling, helper, shared ));
2008
2005
}
2009
2006
}
2010
2007
if (num_routes > 0 || num_circuit > 1 ) {
2011
2008
if (name_filter.Keep (" routing_full_path_lns" )) {
2012
2009
reentrant_interleaved_subsolvers.push_back (std::make_unique<LnsSolver>(
2013
2010
std::make_unique<RoutingFullPathNeighborhoodGenerator>(
2014
2011
helper, name_filter.LastName ()),
2015
- lns_params, helper, shared, routing_lin_level ));
2012
+ lns_params_routing, lns_params_stalling, helper, shared ));
2016
2013
}
2017
2014
}
2018
2015
}
0 commit comments