NUCS 4.0.0__tar.gz → 4.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nucs-4.0.0 → nucs-4.2.0/NUCS.egg-info}/PKG-INFO +1 -1
- {nucs-4.0.0 → nucs-4.2.0}/NUCS.egg-info/SOURCES.txt +3 -0
- {nucs-4.0.0/NUCS.egg-info → nucs-4.2.0}/PKG-INFO +1 -1
- {nucs-4.0.0 → nucs-4.2.0}/docs/source/conf.py +2 -2
- {nucs-4.0.0 → nucs-4.2.0}/nucs/constants.py +6 -2
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/bibd/__main__.py +4 -2
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/golomb/__main__.py +20 -4
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/golomb/golomb_problem.py +12 -20
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/knapsack/__main__.py +3 -2
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/magic_sequence/__main__.py +2 -1
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/schur_lemma/__main__.py +2 -2
- nucs-4.2.0/nucs/examples/tsp/__main__.py +64 -0
- nucs-4.2.0/nucs/examples/tsp/mcp_dom_heuristic.py +59 -0
- nucs-4.2.0/nucs/examples/tsp/mrp_var_heuristic.py +60 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/tsp/total_cost_propagator.py +2 -2
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/tsp/tsp_problem.py +1 -4
- {nucs-4.0.0 → nucs-4.2.0}/nucs/heuristics/first_not_instantiated_var_heuristic.py +4 -4
- {nucs-4.0.0 → nucs-4.2.0}/nucs/heuristics/greatest_domain_var_heuristic.py +4 -4
- {nucs-4.0.0 → nucs-4.2.0}/nucs/heuristics/heuristics.py +5 -3
- {nucs-4.0.0 → nucs-4.2.0}/nucs/heuristics/max_regret_var_heuristic.py +5 -6
- {nucs-4.0.0 → nucs-4.2.0}/nucs/heuristics/max_value_dom_heuristic.py +9 -9
- {nucs-4.0.0 → nucs-4.2.0}/nucs/heuristics/min_cost_dom_heuristic.py +5 -5
- {nucs-4.0.0 → nucs-4.2.0}/nucs/heuristics/min_value_dom_heuristic.py +9 -9
- {nucs-4.0.0 → nucs-4.2.0}/nucs/heuristics/smallest_domain_var_heuristic.py +4 -4
- nucs-4.2.0/nucs/heuristics/split_high_dom_heuristic.py +58 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/heuristics/split_low_dom_heuristic.py +9 -9
- {nucs-4.0.0 → nucs-4.2.0}/nucs/heuristics/value_dom_heuristic.py +15 -15
- {nucs-4.0.0 → nucs-4.2.0}/nucs/problems/problem.py +1 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/affine_eq_propagator.py +1 -1
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/affine_geq_propagator.py +1 -1
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/affine_leq_propagator.py +1 -1
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/element_iv_propagator.py +3 -3
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/propagators.py +1 -1
- {nucs-4.0.0 → nucs-4.2.0}/nucs/solvers/backtrack_solver.py +97 -82
- {nucs-4.0.0 → nucs-4.2.0}/nucs/solvers/choice_points.py +59 -1
- {nucs-4.0.0 → nucs-4.2.0}/nucs/solvers/multiprocessing_solver.py +10 -7
- {nucs-4.0.0 → nucs-4.2.0}/nucs/solvers/shaving_consistency_algorithm.py +3 -3
- {nucs-4.0.0 → nucs-4.2.0}/nucs/solvers/solver.py +3 -45
- {nucs-4.0.0 → nucs-4.2.0}/pyproject.toml +1 -1
- {nucs-4.0.0 → nucs-4.2.0}/tests/examples/test_bibd.py +3 -3
- {nucs-4.0.0 → nucs-4.2.0}/tests/examples/test_golomb.py +2 -7
- {nucs-4.0.0 → nucs-4.2.0}/tests/examples/test_magic_sequence.py +1 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/solvers/test_backtrack_solver.py +31 -1
- {nucs-4.0.0 → nucs-4.2.0}/tests/solvers/test_multiprocessing_solver.py +28 -23
- nucs-4.0.0/nucs/examples/tsp/__main__.py +0 -43
- {nucs-4.0.0 → nucs-4.2.0}/LICENSE.md +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/NUCS.egg-info/dependency_links.txt +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/NUCS.egg-info/requires.txt +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/NUCS.egg-info/top_level.txt +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/README.md +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/alpha/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/alpha/__main__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/alpha/alpha_problem.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/bibd/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/bibd/bibd_problem.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/donald/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/donald/__main__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/donald/donald_problem.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/golomb/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/knapsack/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/knapsack/knapsack_problem.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/magic_sequence/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/magic_sequence/magic_sequence_problem.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/magic_square/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/magic_square/__main__.py +1 -1
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/magic_square/magic_square_problem.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/quasigroup/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/quasigroup/__main__.py +1 -1
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/quasigroup/quasigroup_problem.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/queens/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/queens/__main__.py +2 -2
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/queens/queens_problem.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/schur_lemma/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/schur_lemma/schur_lemma_problem.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/sports_tournament_scheduling/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/sports_tournament_scheduling/__main__.py +1 -1
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/sports_tournament_scheduling/sports_tournament_scheduling_problem.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/sudoku/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/sudoku/sudoku_problem.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/tsp/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/examples/tsp/tsp_instances.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/heuristics/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/heuristics/mid_value_dom_heuristic.py +3 -3
- {nucs-4.0.0 → nucs-4.2.0}/nucs/numba_helper.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/numpy_helper.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/problems/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/problems/circuit_problem.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/problems/latin_square_problem.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/alldifferent_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/and_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/count_eq_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/dummy_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/element_lic_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/element_liv_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/exactly_eq_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/exactly_true_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/gcc_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/lexicographic_leq_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/max_eq_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/max_leq_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/min_eq_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/min_geq_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/no_sub_cycle_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/relation_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/propagators/scc_propagator.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/solvers/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/solvers/bound_consistency_algorithm.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/nucs/solvers/consistency_algorithms.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/setup.cfg +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/examples/test_alpha.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/examples/test_donald.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/examples/test_knapsack.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/examples/test_latin_square.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/examples/test_magic_square.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/examples/test_quasigroup.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/examples/test_queens.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/examples/test_schur_lemma.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/examples/test_sports_tournament_scheduling.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/examples/test_sudokus.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/examples/test_tsp.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/heuristics/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/heuristics/test_max_value_dom_heuristic.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/heuristics/test_mid_value_dom_heuristic.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/heuristics/test_min_value_dom_heuristic.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/problems/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/problems/test_circuit_problem.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/problems/test_problem.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/__init__.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_affine_eq.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_affine_geq.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_affine_leq.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_alldifferent.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_count_eq.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_element_iv.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_element_lic.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_element_liv.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_exactly_eq.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_gcc.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_lexicographic_leq.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_max_eq.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_max_leq.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_min_eq.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_min_geq.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_no_sub_cycle.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_relation.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/propagators/test_scc.py +0 -0
- {nucs-4.0.0 → nucs-4.2.0}/tests/solvers/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: NUCS
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.2.0
|
|
4
4
|
Summary: A Numpy and Numba based Python library for solving Constraint Satisfaction Problems over finite domains
|
|
5
5
|
Author-email: Yan Georget <yan.georget@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/yangeorget/nucs
|
|
@@ -49,6 +49,8 @@ nucs/examples/sudoku/__init__.py
|
|
|
49
49
|
nucs/examples/sudoku/sudoku_problem.py
|
|
50
50
|
nucs/examples/tsp/__init__.py
|
|
51
51
|
nucs/examples/tsp/__main__.py
|
|
52
|
+
nucs/examples/tsp/mcp_dom_heuristic.py
|
|
53
|
+
nucs/examples/tsp/mrp_var_heuristic.py
|
|
52
54
|
nucs/examples/tsp/total_cost_propagator.py
|
|
53
55
|
nucs/examples/tsp/tsp_instances.py
|
|
54
56
|
nucs/examples/tsp/tsp_problem.py
|
|
@@ -62,6 +64,7 @@ nucs/heuristics/mid_value_dom_heuristic.py
|
|
|
62
64
|
nucs/heuristics/min_cost_dom_heuristic.py
|
|
63
65
|
nucs/heuristics/min_value_dom_heuristic.py
|
|
64
66
|
nucs/heuristics/smallest_domain_var_heuristic.py
|
|
67
|
+
nucs/heuristics/split_high_dom_heuristic.py
|
|
65
68
|
nucs/heuristics/split_low_dom_heuristic.py
|
|
66
69
|
nucs/heuristics/value_dom_heuristic.py
|
|
67
70
|
nucs/problems/__init__.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: NUCS
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.2.0
|
|
4
4
|
Summary: A Numpy and Numba based Python library for solving Constraint Satisfaction Problems over finite domains
|
|
5
5
|
Author-email: Yan Georget <yan.georget@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/yangeorget/nucs
|
|
@@ -14,6 +14,10 @@ import os
|
|
|
14
14
|
|
|
15
15
|
from numba import bool, int32, int64, types, uint8, uint16 # type: ignore
|
|
16
16
|
|
|
17
|
+
OPT_RESET = "RESET"
|
|
18
|
+
OPT_PRUNE = "PRUNE"
|
|
19
|
+
OPT_MODES = [OPT_RESET, OPT_PRUNE]
|
|
20
|
+
|
|
17
21
|
RG_START = 0 # index corresponding the start of a values range
|
|
18
22
|
RG_END = 1 # index corresponding the end of a values range
|
|
19
23
|
|
|
@@ -61,18 +65,18 @@ SIGNATURE_CONSISTENCY_ALG = int64(
|
|
|
61
65
|
uint16[:], # decision_domains
|
|
62
66
|
)
|
|
63
67
|
SIGNATURE_DOM_HEURISTIC = int64(
|
|
64
|
-
int64[:, :], # dom_heuristic_params
|
|
65
68
|
int32[:, :, :], # shr_domains_stack
|
|
66
69
|
bool[:, :], # not_entailed_propagators_stack
|
|
67
70
|
uint16[:, :], # dom_update_stack
|
|
68
71
|
uint8[:], # stacks_top
|
|
69
72
|
int64, # dom_idx
|
|
73
|
+
int64[:, :], # dom_heuristic_params
|
|
70
74
|
)
|
|
71
75
|
SIGNATURE_VAR_HEURISTIC = int64(
|
|
72
|
-
int64[:, :], # var_heuristic_params
|
|
73
76
|
uint16[:], # decision_variables
|
|
74
77
|
int32[:, :, :], # shr_domains_stack
|
|
75
78
|
uint8[:], # stacks_top
|
|
79
|
+
int64[:, :], # var_heuristic_params
|
|
76
80
|
)
|
|
77
81
|
|
|
78
82
|
|
|
@@ -28,10 +28,12 @@ if __name__ == "__main__":
|
|
|
28
28
|
parser.add_argument("-r", type=int)
|
|
29
29
|
parser.add_argument("-k", type=int)
|
|
30
30
|
parser.add_argument("-l", type=int)
|
|
31
|
-
parser.add_argument("--symmetry_breaking", action=argparse.BooleanOptionalAction, default=True)
|
|
32
31
|
parser.add_argument("--log_level", choices=LOG_LEVELS, default=LOG_LEVEL_INFO)
|
|
32
|
+
parser.add_argument("--symmetry_breaking", action=argparse.BooleanOptionalAction, default=True)
|
|
33
33
|
args = parser.parse_args()
|
|
34
34
|
problem = BIBDProblem(args.v, args.b, args.r, args.k, args.l, args.symmetry_breaking)
|
|
35
|
-
solver = BacktrackSolver(
|
|
35
|
+
solver = BacktrackSolver(
|
|
36
|
+
problem, dom_heuristic_idx=DOM_HEURISTIC_MAX_VALUE, log_level=args.log_level, stack_max_height=128
|
|
37
|
+
)
|
|
36
38
|
solver.solve_all()
|
|
37
39
|
print(solver.get_statistics())
|
|
@@ -14,23 +14,39 @@ import argparse
|
|
|
14
14
|
|
|
15
15
|
from rich import print
|
|
16
16
|
|
|
17
|
-
from nucs.constants import LOG_LEVEL_INFO, LOG_LEVELS
|
|
17
|
+
from nucs.constants import LOG_LEVEL_INFO, LOG_LEVELS, OPT_MODES, OPT_PRUNE
|
|
18
18
|
from nucs.examples.golomb.golomb_problem import GolombProblem, golomb_consistency_algorithm
|
|
19
19
|
from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
20
20
|
from nucs.solvers.consistency_algorithms import register_consistency_algorithm
|
|
21
|
+
from nucs.solvers.multiprocessing_solver import MultiprocessingSolver
|
|
21
22
|
|
|
22
23
|
# Run with the following command (the second run is much faster because the code has been compiled):
|
|
23
24
|
# NUMBA_CACHE_DIR=.numba/cache python -m nucs.examples.golomb -n 10 --symmetry_breaking
|
|
24
25
|
if __name__ == "__main__":
|
|
25
26
|
parser = argparse.ArgumentParser()
|
|
26
27
|
parser.add_argument("-n", type=int, default=10)
|
|
27
|
-
parser.add_argument("--symmetry_breaking", action=argparse.BooleanOptionalAction, default=True)
|
|
28
28
|
parser.add_argument("--log_level", choices=LOG_LEVELS, default=LOG_LEVEL_INFO)
|
|
29
|
+
parser.add_argument("--opt_mode", choices=OPT_MODES, default=OPT_PRUNE)
|
|
30
|
+
parser.add_argument("--processors", type=int, default=1)
|
|
31
|
+
parser.add_argument("--symmetry_breaking", action=argparse.BooleanOptionalAction, default=True)
|
|
29
32
|
args = parser.parse_args()
|
|
30
33
|
problem = GolombProblem(args.n, args.symmetry_breaking)
|
|
31
34
|
consistency_alg_golomb = register_consistency_algorithm(golomb_consistency_algorithm)
|
|
32
|
-
solver =
|
|
33
|
-
|
|
35
|
+
solver = (
|
|
36
|
+
MultiprocessingSolver(
|
|
37
|
+
[
|
|
38
|
+
BacktrackSolver(
|
|
39
|
+
prob, consistency_alg_idx=consistency_alg_golomb, log_level=args.log_level, stack_max_height=128
|
|
40
|
+
)
|
|
41
|
+
for prob in problem.split(args.processors, 0)
|
|
42
|
+
]
|
|
43
|
+
)
|
|
44
|
+
if args.processors > 1
|
|
45
|
+
else BacktrackSolver(
|
|
46
|
+
problem, consistency_alg_idx=consistency_alg_golomb, log_level=args.log_level, stack_max_height=128
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
solution = solver.minimize(problem.length_idx, mode=args.opt_mode)
|
|
34
50
|
print(solver.get_statistics())
|
|
35
51
|
if solution is not None:
|
|
36
52
|
print(solution[: (args.n - 1)])
|
|
@@ -26,7 +26,7 @@ GOLOMB_LENGTHS = np.array([0, 0, 1, 3, 6, 11, 17, 25, 34, 44, 55, 72, 85, 106, 1
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
@njit(cache=True)
|
|
29
|
-
def sum_first(n:
|
|
29
|
+
def sum_first(n: int) -> int:
|
|
30
30
|
"""
|
|
31
31
|
Returns the sum of the first n integers.
|
|
32
32
|
:param n: an integer
|
|
@@ -36,7 +36,7 @@ def sum_first(n: np.uint32) -> np.uint32:
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
@njit(cache=True)
|
|
39
|
-
def index(mark_nb:
|
|
39
|
+
def index(mark_nb: int, i: int, j: int) -> int:
|
|
40
40
|
"""
|
|
41
41
|
Returns the index of the distance variable between two marks.
|
|
42
42
|
:param mark_nb: the total number of marks
|
|
@@ -47,22 +47,6 @@ def index(mark_nb: np.uint32, i: np.uint32, j: np.uint32) -> np.uint32:
|
|
|
47
47
|
return i * mark_nb - sum_first(i) + j - i - 1
|
|
48
48
|
|
|
49
49
|
|
|
50
|
-
@njit(cache=True)
|
|
51
|
-
def init_domains(dist_nb: int, mark_nb: int) -> NDArray:
|
|
52
|
-
"""
|
|
53
|
-
Returns the domains.
|
|
54
|
-
:param dist_nb: the number of distances
|
|
55
|
-
:param mark_nb: the number of marks
|
|
56
|
-
:return: a Numpy array of domains
|
|
57
|
-
"""
|
|
58
|
-
domains = np.empty((dist_nb, 2), dtype=np.int32)
|
|
59
|
-
for i in range(0, mark_nb - 1):
|
|
60
|
-
for j in range(i + 1, mark_nb):
|
|
61
|
-
domains[index(mark_nb, i, j), MIN] = GOLOMB_LENGTHS[j - i + 1] if j - i + 1 < mark_nb else sum_first(j - i)
|
|
62
|
-
domains[:, MAX] = sum_first(dist_nb)
|
|
63
|
-
return domains
|
|
64
|
-
|
|
65
|
-
|
|
66
50
|
class GolombProblem(Problem):
|
|
67
51
|
"""
|
|
68
52
|
This is the famous Golomb ruler problem.
|
|
@@ -77,7 +61,15 @@ class GolombProblem(Problem):
|
|
|
77
61
|
"""
|
|
78
62
|
|
|
79
63
|
def __init__(self, mark_nb: int, symmetry_breaking: bool = True) -> None:
|
|
80
|
-
|
|
64
|
+
dist_nb = sum_first(mark_nb - 1)
|
|
65
|
+
domains = np.empty((dist_nb, 2), dtype=np.int32)
|
|
66
|
+
for i in range(0, mark_nb - 1):
|
|
67
|
+
for j in range(i + 1, mark_nb):
|
|
68
|
+
domains[index(mark_nb, i, j), MIN] = (
|
|
69
|
+
GOLOMB_LENGTHS[j - i + 1] if j - i + 1 < mark_nb else sum_first(j - i)
|
|
70
|
+
)
|
|
71
|
+
domains[:, MAX] = sum_first(dist_nb) - sum_first(dist_nb - mark_nb)
|
|
72
|
+
super().__init__(domains)
|
|
81
73
|
self.length_idx = index(mark_nb, 0, mark_nb - 1) # we want to minimize this
|
|
82
74
|
# dist_ij = mark_j - mark_i for j > i
|
|
83
75
|
# mark_j = dist_0j for j > 0
|
|
@@ -142,7 +134,7 @@ def golomb_consistency_algorithm(
|
|
|
142
134
|
# first prune the search space
|
|
143
135
|
mark_nb = (1 + int(math.sqrt(8 * len(dom_indices_arr) + 1))) // 2
|
|
144
136
|
ni_var_idx = first_not_instantiated_var_heuristic(
|
|
145
|
-
|
|
137
|
+
decision_domains, shr_domains_stack, stacks_top, None
|
|
146
138
|
) # no domains shared between vars
|
|
147
139
|
if 1 < ni_var_idx < mark_nb - 1: # otherwise useless
|
|
148
140
|
used_distance = np.zeros(sum_first(mark_nb - 2) + 1, dtype=np.bool)
|
|
@@ -14,7 +14,7 @@ import argparse
|
|
|
14
14
|
|
|
15
15
|
from rich import print
|
|
16
16
|
|
|
17
|
-
from nucs.constants import LOG_LEVEL_INFO, LOG_LEVELS
|
|
17
|
+
from nucs.constants import LOG_LEVEL_INFO, LOG_LEVELS, OPT_MODES, OPT_RESET
|
|
18
18
|
from nucs.examples.knapsack.knapsack_problem import KnapsackProblem
|
|
19
19
|
from nucs.heuristics.heuristics import DOM_HEURISTIC_MAX_VALUE, VAR_HEURISTIC_FIRST_NOT_INSTANTIATED
|
|
20
20
|
from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
@@ -24,6 +24,7 @@ from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
|
24
24
|
if __name__ == "__main__":
|
|
25
25
|
parser = argparse.ArgumentParser()
|
|
26
26
|
parser.add_argument("--log_level", choices=LOG_LEVELS, default=LOG_LEVEL_INFO)
|
|
27
|
+
parser.add_argument("--opt_mode", choices=OPT_MODES, default=OPT_RESET)
|
|
27
28
|
args = parser.parse_args()
|
|
28
29
|
problem = KnapsackProblem(
|
|
29
30
|
[40, 40, 38, 38, 36, 36, 34, 34, 32, 32, 30, 30, 28, 28, 26, 26, 24, 24, 22, 22],
|
|
@@ -36,6 +37,6 @@ if __name__ == "__main__":
|
|
|
36
37
|
dom_heuristic_idx=DOM_HEURISTIC_MAX_VALUE,
|
|
37
38
|
log_level=args.log_level,
|
|
38
39
|
)
|
|
39
|
-
solution = solver.maximize(problem.weight)
|
|
40
|
+
solution = solver.maximize(problem.weight, mode=args.opt_mode)
|
|
40
41
|
print(solver.get_statistics())
|
|
41
42
|
print(solution)
|
|
@@ -23,8 +23,8 @@ from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
|
23
23
|
# NUMBA_CACHE_DIR=.numba/cache python -m nucs.examples.magic_sequence -n 100
|
|
24
24
|
if __name__ == "__main__":
|
|
25
25
|
parser = argparse.ArgumentParser()
|
|
26
|
-
parser.add_argument("-n", type=int, default=100)
|
|
27
26
|
parser.add_argument("--log_level", choices=LOG_LEVELS, default=LOG_LEVEL_INFO)
|
|
27
|
+
parser.add_argument("-n", type=int, default=100)
|
|
28
28
|
args = parser.parse_args()
|
|
29
29
|
problem = MagicSequenceProblem(args.n)
|
|
30
30
|
solver = BacktrackSolver(
|
|
@@ -33,6 +33,7 @@ if __name__ == "__main__":
|
|
|
33
33
|
var_heuristic_idx=VAR_HEURISTIC_FIRST_NOT_INSTANTIATED,
|
|
34
34
|
dom_heuristic_idx=DOM_HEURISTIC_MIN_VALUE,
|
|
35
35
|
log_level=args.log_level,
|
|
36
|
+
stack_max_height=128,
|
|
36
37
|
)
|
|
37
38
|
solver.solve_all()
|
|
38
39
|
print(solver.get_statistics())
|
|
@@ -22,11 +22,11 @@ from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
|
22
22
|
# NUMBA_CACHE_DIR=.numba/cache python -m nucs.examples.schur_lemma -n 20 --symmetry_breaking
|
|
23
23
|
if __name__ == "__main__":
|
|
24
24
|
parser = argparse.ArgumentParser()
|
|
25
|
-
parser.add_argument("-n", type=int, default=20)
|
|
26
25
|
parser.add_argument("--log_level", choices=LOG_LEVELS, default=LOG_LEVEL_INFO)
|
|
26
|
+
parser.add_argument("-n", type=int, default=20)
|
|
27
27
|
parser.add_argument("--symmetry_breaking", action=argparse.BooleanOptionalAction, default=True)
|
|
28
28
|
args = parser.parse_args()
|
|
29
29
|
problem = SchurLemmaProblem(args.n, args.symmetry_breaking)
|
|
30
|
-
solver = BacktrackSolver(problem, log_level=args.log_level)
|
|
30
|
+
solver = BacktrackSolver(problem, log_level=args.log_level, stack_max_height=128)
|
|
31
31
|
solver.solve_all()
|
|
32
32
|
print(solver.get_statistics())
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
# __ _ _____ _____
|
|
3
|
+
# | \ | | / ____| / ____|
|
|
4
|
+
# | \| | _ _ | | | (___
|
|
5
|
+
# | . ` | | | | | | | \___ \
|
|
6
|
+
# | |\ | | |_| | | |____ ____) |
|
|
7
|
+
# |_| \_| \__,_| \_____| |_____/
|
|
8
|
+
#
|
|
9
|
+
# Fast constraint solving in Python - https://github.com/yangeorget/nucs
|
|
10
|
+
#
|
|
11
|
+
# Copyright 2024 - Yan Georget
|
|
12
|
+
###############################################################################
|
|
13
|
+
import argparse
|
|
14
|
+
|
|
15
|
+
from nucs.constants import LOG_LEVEL_INFO, LOG_LEVELS, OPT_MODES, OPT_PRUNE
|
|
16
|
+
from nucs.examples.tsp.tsp_instances import TSP_INSTANCES
|
|
17
|
+
from nucs.examples.tsp.tsp_problem import TSPProblem
|
|
18
|
+
from nucs.heuristics.heuristics import DOM_HEURISTIC_MIN_COST, VAR_HEURISTIC_MAX_REGRET
|
|
19
|
+
from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
20
|
+
from nucs.solvers.consistency_algorithms import CONSISTENCY_ALG_BC, CONSISTENCY_ALG_SHAVING
|
|
21
|
+
from nucs.solvers.multiprocessing_solver import MultiprocessingSolver
|
|
22
|
+
|
|
23
|
+
# Run with the following command (the second run is much faster because the code has been compiled):
|
|
24
|
+
# NUMBA_CACHE_DIR=.numba/cache python -m nucs.examples.alpha
|
|
25
|
+
if __name__ == "__main__":
|
|
26
|
+
parser = argparse.ArgumentParser()
|
|
27
|
+
parser.add_argument("--log_level", choices=LOG_LEVELS, default=LOG_LEVEL_INFO)
|
|
28
|
+
parser.add_argument("--name", choices=["GR17", "GR21", "GR24"], default="GR17")
|
|
29
|
+
parser.add_argument("--opt_mode", choices=OPT_MODES, default=OPT_PRUNE)
|
|
30
|
+
parser.add_argument("--processors", type=int, default=1)
|
|
31
|
+
parser.add_argument("--shaving", type=bool, action=argparse.BooleanOptionalAction, default=True)
|
|
32
|
+
args = parser.parse_args()
|
|
33
|
+
tsp_instance = TSP_INSTANCES[args.name]
|
|
34
|
+
problem = TSPProblem(tsp_instance)
|
|
35
|
+
solver = (
|
|
36
|
+
MultiprocessingSolver(
|
|
37
|
+
[
|
|
38
|
+
BacktrackSolver(
|
|
39
|
+
prob,
|
|
40
|
+
consistency_alg_idx=CONSISTENCY_ALG_SHAVING if args.shaving else CONSISTENCY_ALG_BC,
|
|
41
|
+
decision_domains=list(range(len(tsp_instance))),
|
|
42
|
+
var_heuristic_idx=VAR_HEURISTIC_MAX_REGRET, # register_var_heuristic(mrp_var_heuristic),
|
|
43
|
+
var_heuristic_params=tsp_instance,
|
|
44
|
+
dom_heuristic_idx=DOM_HEURISTIC_MIN_COST, # register_dom_heuristic(mcp_dom_heuristic),
|
|
45
|
+
dom_heuristic_params=tsp_instance,
|
|
46
|
+
log_level=args.log_level,
|
|
47
|
+
)
|
|
48
|
+
for prob in problem.split(args.processors, 0)
|
|
49
|
+
]
|
|
50
|
+
)
|
|
51
|
+
if args.processors > 1
|
|
52
|
+
else BacktrackSolver(
|
|
53
|
+
problem,
|
|
54
|
+
consistency_alg_idx=CONSISTENCY_ALG_SHAVING if args.shaving else CONSISTENCY_ALG_BC,
|
|
55
|
+
decision_domains=list(range(len(tsp_instance))),
|
|
56
|
+
var_heuristic_idx=VAR_HEURISTIC_MAX_REGRET, # register_var_heuristic(mrp_var_heuristic),
|
|
57
|
+
var_heuristic_params=tsp_instance,
|
|
58
|
+
dom_heuristic_idx=DOM_HEURISTIC_MIN_COST, # register_dom_heuristic(mcp_dom_heuristic),
|
|
59
|
+
dom_heuristic_params=tsp_instance,
|
|
60
|
+
log_level=args.log_level,
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
solution = solver.minimize(problem.shr_domain_nb - 1, mode=args.opt_mode)
|
|
64
|
+
print(solver.get_statistics())
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
# __ _ _____ _____
|
|
3
|
+
# | \ | | / ____| / ____|
|
|
4
|
+
# | \| | _ _ | | | (___
|
|
5
|
+
# | . ` | | | | | | | \___ \
|
|
6
|
+
# | |\ | | |_| | | |____ ____) |
|
|
7
|
+
# |_| \_| \__,_| \_____| |_____/
|
|
8
|
+
#
|
|
9
|
+
# Fast constraint solving in Python - https://github.com/yangeorget/nucs
|
|
10
|
+
#
|
|
11
|
+
# Copyright 2024 - Yan Georget
|
|
12
|
+
###############################################################################
|
|
13
|
+
import sys
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
from numba import njit # type: ignore
|
|
17
|
+
from numpy.typing import NDArray
|
|
18
|
+
|
|
19
|
+
from nucs.constants import MAX, MIN
|
|
20
|
+
from nucs.heuristics.value_dom_heuristic import value_dom_heuristic
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@njit(cache=True)
|
|
24
|
+
def mcp_dom_heuristic(
|
|
25
|
+
shr_domains_stack: NDArray,
|
|
26
|
+
not_entailed_propagators_stack: NDArray,
|
|
27
|
+
dom_update_stack: NDArray,
|
|
28
|
+
stacks_top: NDArray,
|
|
29
|
+
dom_idx: int,
|
|
30
|
+
params: NDArray,
|
|
31
|
+
) -> int:
|
|
32
|
+
"""
|
|
33
|
+
Chooses the value that minimizes the cost.
|
|
34
|
+
:param shr_domains_stack: the stack of shared domains
|
|
35
|
+
:param not_entailed_propagators_stack: the stack of not entailed propagators
|
|
36
|
+
:param dom_update_stack: the stack of domain updates
|
|
37
|
+
:param stacks_top: the index of the top of the stacks as a Numpy array
|
|
38
|
+
:param dom_idx: the index of the shared domain
|
|
39
|
+
:param params: a two-dimensional (first dimension correspond to variables, second to values) costs array
|
|
40
|
+
:return: the events
|
|
41
|
+
"""
|
|
42
|
+
top = stacks_top[0]
|
|
43
|
+
n = len(params)
|
|
44
|
+
used = np.zeros(n, dtype=np.bool)
|
|
45
|
+
for i in range(n):
|
|
46
|
+
if shr_domains_stack[top, i, MIN] == shr_domains_stack[top, i, MAX]:
|
|
47
|
+
used[shr_domains_stack[top, i, MIN]] = True
|
|
48
|
+
best_cost = sys.maxsize
|
|
49
|
+
best_value = -1
|
|
50
|
+
shr_domain = shr_domains_stack[top, dom_idx]
|
|
51
|
+
for value in range(shr_domain[MIN], shr_domain[MAX] + 1):
|
|
52
|
+
if not used[value]:
|
|
53
|
+
cost = params[dom_idx][value]
|
|
54
|
+
if 0 < cost < best_cost:
|
|
55
|
+
best_cost = cost
|
|
56
|
+
best_value = value
|
|
57
|
+
return value_dom_heuristic(
|
|
58
|
+
shr_domains_stack, not_entailed_propagators_stack, dom_update_stack, stacks_top, dom_idx, best_value, params
|
|
59
|
+
)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
# __ _ _____ _____
|
|
3
|
+
# | \ | | / ____| / ____|
|
|
4
|
+
# | \| | _ _ | | | (___
|
|
5
|
+
# | . ` | | | | | | | \___ \
|
|
6
|
+
# | |\ | | |_| | | |____ ____) |
|
|
7
|
+
# |_| \_| \__,_| \_____| |_____/
|
|
8
|
+
#
|
|
9
|
+
# Fast constraint solving in Python - https://github.com/yangeorget/nucs
|
|
10
|
+
#
|
|
11
|
+
# Copyright 2024 - Yan Georget
|
|
12
|
+
###############################################################################
|
|
13
|
+
import sys
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
from numba import njit # type: ignore
|
|
17
|
+
from numpy.typing import NDArray
|
|
18
|
+
|
|
19
|
+
from nucs.constants import MAX, MIN
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@njit(cache=True)
|
|
23
|
+
def mrp_var_heuristic(
|
|
24
|
+
decision_domains: NDArray, shr_domains_stack: NDArray, stacks_top: NDArray, params: NDArray
|
|
25
|
+
) -> int:
|
|
26
|
+
"""
|
|
27
|
+
Chooses the variable with the maximal regret (difference between best and second-best value).
|
|
28
|
+
:param decision_domains: the indices of a subset of the shared domains
|
|
29
|
+
:param shr_domains_stack: the stack of shared domains
|
|
30
|
+
:param stacks_top: the index of the top of the stacks as a Numpy array
|
|
31
|
+
:param params: a two-dimensional (first dimension correspond to variables, second to values) costs array
|
|
32
|
+
:return: the index of the shared domain
|
|
33
|
+
"""
|
|
34
|
+
top = stacks_top[0]
|
|
35
|
+
n = len(decision_domains)
|
|
36
|
+
used = np.zeros(n, dtype=np.bool)
|
|
37
|
+
for i in range(n):
|
|
38
|
+
if shr_domains_stack[top, i, MIN] == shr_domains_stack[top, i, MAX]:
|
|
39
|
+
used[shr_domains_stack[top, i, MIN]] = True
|
|
40
|
+
max_regret = 0
|
|
41
|
+
best_idx = -1
|
|
42
|
+
for dom_idx in decision_domains:
|
|
43
|
+
shr_domain = shr_domains_stack[top, dom_idx]
|
|
44
|
+
size = shr_domain[MAX] - shr_domain[MIN] # actually this is size - 1
|
|
45
|
+
if 0 < size:
|
|
46
|
+
best_cost = second_cost = sys.maxsize
|
|
47
|
+
for value in range(shr_domain[MIN], shr_domain[MAX] + 1):
|
|
48
|
+
if not used[value]:
|
|
49
|
+
cost = params[dom_idx][value]
|
|
50
|
+
if cost > 0:
|
|
51
|
+
if cost < best_cost:
|
|
52
|
+
second_cost = best_cost
|
|
53
|
+
best_cost = cost
|
|
54
|
+
elif cost < second_cost:
|
|
55
|
+
second_cost = cost
|
|
56
|
+
regret = second_cost - best_cost
|
|
57
|
+
if max_regret < regret:
|
|
58
|
+
best_idx = dom_idx
|
|
59
|
+
max_regret = regret
|
|
60
|
+
return best_idx
|
|
@@ -55,11 +55,11 @@ def compute_domains_total_cost(domains: NDArray, parameters: NDArray) -> int:
|
|
|
55
55
|
used[domains[i, MIN]] = True
|
|
56
56
|
global_min = global_max = 0
|
|
57
57
|
for i in range(n):
|
|
58
|
-
local_min = sys.maxsize
|
|
59
|
-
local_max = 0
|
|
60
58
|
if domains[i, MIN] == domains[i, MAX]:
|
|
61
59
|
local_min = local_max = parameters[i * n + domains[i, MIN]]
|
|
62
60
|
else:
|
|
61
|
+
local_min = sys.maxsize
|
|
62
|
+
local_max = 0
|
|
63
63
|
for value in range(domains[i, MIN], domains[i, MAX] + 1):
|
|
64
64
|
if not used[value]:
|
|
65
65
|
cost = parameters[i * n + value]
|
|
@@ -38,13 +38,10 @@ class TSPProblem(CircuitProblem):
|
|
|
38
38
|
for i in range(n):
|
|
39
39
|
self.add_propagator(([i, cost_vars + i], ALG_ELEMENT_IV, cost_rows[i]))
|
|
40
40
|
self.add_propagator((list(range(cost_vars, cost_vars + n + 1)), ALG_AFFINE_EQ, [1] * n + [-1, 0]))
|
|
41
|
-
alg_total_cost = register_propagator(
|
|
42
|
-
get_triggers_total_cost, get_complexity_total_cost, compute_domains_total_cost
|
|
43
|
-
)
|
|
44
41
|
self.add_propagator(
|
|
45
42
|
(
|
|
46
43
|
list(range(0, n)) + [total_cost_var],
|
|
47
|
-
|
|
44
|
+
register_propagator(get_triggers_total_cost, get_complexity_total_cost, compute_domains_total_cost),
|
|
48
45
|
[cost for cost_row in cost_rows for cost in cost_row],
|
|
49
46
|
)
|
|
50
47
|
)
|
|
@@ -18,18 +18,18 @@ from nucs.constants import MAX, MIN
|
|
|
18
18
|
|
|
19
19
|
@njit(cache=True)
|
|
20
20
|
def first_not_instantiated_var_heuristic(
|
|
21
|
-
|
|
21
|
+
decision_domains: NDArray, shr_domains_stack: NDArray, stacks_top: NDArray, params: NDArray
|
|
22
22
|
) -> int:
|
|
23
23
|
"""
|
|
24
24
|
Chooses the first non-instantiated shared domain.
|
|
25
|
-
:param params: a two-dimensional parameters array, unused here
|
|
26
25
|
:param decision_domains: the indices of a subset of the shared domains
|
|
27
26
|
:param shr_domains_stack: the stack of shared domains
|
|
28
27
|
:param stacks_top: the index of the top of the stacks as a Numpy array
|
|
28
|
+
:param params: a two-dimensional parameters array, unused here
|
|
29
29
|
:return: the index of the shared domain
|
|
30
30
|
"""
|
|
31
|
-
|
|
31
|
+
top = stacks_top[0]
|
|
32
32
|
for dom_idx in decision_domains:
|
|
33
|
-
if shr_domains_stack[
|
|
33
|
+
if shr_domains_stack[top, dom_idx, MIN] < shr_domains_stack[top, dom_idx, MAX]:
|
|
34
34
|
return dom_idx
|
|
35
35
|
return -1 # cannot happen
|
|
@@ -18,21 +18,21 @@ from nucs.constants import MAX, MIN
|
|
|
18
18
|
|
|
19
19
|
@njit(cache=True)
|
|
20
20
|
def greatest_domain_var_heuristic(
|
|
21
|
-
|
|
21
|
+
decision_domains: NDArray, shr_domains_stack: NDArray, stacks_top: NDArray, params: NDArray
|
|
22
22
|
) -> int:
|
|
23
23
|
"""
|
|
24
24
|
Chooses the greatest shared domain and which is not instantiated.
|
|
25
|
-
:param params: a two-dimensional parameters array, unused here
|
|
26
25
|
:param decision_domains: the indices of a subset of the shared domains
|
|
27
26
|
:param shr_domains_stack: the stack of shared domains
|
|
28
27
|
:param stacks_top: the index of the top of the stacks as a Numpy array
|
|
28
|
+
:param params: a two-dimensional parameters array, unused here
|
|
29
29
|
:return: the index of the shared domain
|
|
30
30
|
"""
|
|
31
31
|
max_size = 0
|
|
32
32
|
max_idx = -1
|
|
33
|
-
|
|
33
|
+
top = stacks_top[0]
|
|
34
34
|
for dom_idx in decision_domains:
|
|
35
|
-
shr_domain = shr_domains_stack[
|
|
35
|
+
shr_domain = shr_domains_stack[top, dom_idx]
|
|
36
36
|
size = shr_domain[MAX] - shr_domain[MIN] # actually this is size - 1
|
|
37
37
|
if max_size < size:
|
|
38
38
|
max_idx = dom_idx
|
|
@@ -20,6 +20,7 @@ from nucs.heuristics.mid_value_dom_heuristic import mid_value_dom_heuristic
|
|
|
20
20
|
from nucs.heuristics.min_cost_dom_heuristic import min_cost_dom_heuristic
|
|
21
21
|
from nucs.heuristics.min_value_dom_heuristic import min_value_dom_heuristic
|
|
22
22
|
from nucs.heuristics.smallest_domain_var_heuristic import smallest_domain_var_heuristic
|
|
23
|
+
from nucs.heuristics.split_high_dom_heuristic import split_high_dom_heuristic
|
|
23
24
|
from nucs.heuristics.split_low_dom_heuristic import split_low_dom_heuristic
|
|
24
25
|
|
|
25
26
|
VAR_HEURISTIC_FCTS = []
|
|
@@ -47,12 +48,13 @@ def register_dom_heuristic(dom_heuristic_fct: Callable) -> int:
|
|
|
47
48
|
|
|
48
49
|
|
|
49
50
|
VAR_HEURISTIC_FIRST_NOT_INSTANTIATED = register_var_heuristic(first_not_instantiated_var_heuristic)
|
|
50
|
-
VAR_HEURISTIC_SMALLEST_DOMAIN = register_var_heuristic(smallest_domain_var_heuristic)
|
|
51
51
|
VAR_HEURISTIC_GREATEST_DOMAIN = register_var_heuristic(greatest_domain_var_heuristic)
|
|
52
52
|
VAR_HEURISTIC_MAX_REGRET = register_var_heuristic(max_regret_var_heuristic)
|
|
53
|
+
VAR_HEURISTIC_SMALLEST_DOMAIN = register_var_heuristic(smallest_domain_var_heuristic)
|
|
53
54
|
|
|
54
|
-
DOM_HEURISTIC_MIN_VALUE = register_dom_heuristic(min_value_dom_heuristic)
|
|
55
55
|
DOM_HEURISTIC_MAX_VALUE = register_dom_heuristic(max_value_dom_heuristic)
|
|
56
|
-
DOM_HEURISTIC_SPLIT_LOW = register_dom_heuristic(split_low_dom_heuristic)
|
|
57
56
|
DOM_HEURISTIC_MID_VALUE = register_dom_heuristic(mid_value_dom_heuristic)
|
|
58
57
|
DOM_HEURISTIC_MIN_COST = register_dom_heuristic(min_cost_dom_heuristic)
|
|
58
|
+
DOM_HEURISTIC_MIN_VALUE = register_dom_heuristic(min_value_dom_heuristic)
|
|
59
|
+
DOM_HEURISTIC_SPLIT_HIGH = register_dom_heuristic(split_high_dom_heuristic)
|
|
60
|
+
DOM_HEURISTIC_SPLIT_LOW = register_dom_heuristic(split_low_dom_heuristic)
|
|
@@ -20,23 +20,22 @@ from nucs.constants import MAX, MIN
|
|
|
20
20
|
|
|
21
21
|
@njit(cache=True)
|
|
22
22
|
def max_regret_var_heuristic(
|
|
23
|
-
|
|
23
|
+
decision_domains: NDArray, shr_domains_stack: NDArray, stacks_top: NDArray, params: NDArray
|
|
24
24
|
) -> int:
|
|
25
25
|
"""
|
|
26
26
|
Chooses the variable with the maximal regret (difference between best and second-best value).
|
|
27
|
-
:param params: a two-dimensional (first dimension correspond to variables, second to values) costs array
|
|
28
27
|
:param decision_domains: the indices of a subset of the shared domains
|
|
29
28
|
:param shr_domains_stack: the stack of shared domains
|
|
30
29
|
:param stacks_top: the index of the top of the stacks as a Numpy array
|
|
30
|
+
:param params: a two-dimensional (first dimension correspond to variables, second to values) costs array
|
|
31
31
|
:return: the index of the shared domain
|
|
32
32
|
"""
|
|
33
33
|
max_regret = 0
|
|
34
34
|
best_idx = -1
|
|
35
|
-
|
|
35
|
+
top = stacks_top[0]
|
|
36
36
|
for dom_idx in decision_domains:
|
|
37
|
-
shr_domain = shr_domains_stack[
|
|
38
|
-
|
|
39
|
-
if 0 < size:
|
|
37
|
+
shr_domain = shr_domains_stack[top, dom_idx]
|
|
38
|
+
if 0 < shr_domain[MAX] - shr_domain[MIN]:
|
|
40
39
|
best_cost = sys.maxsize
|
|
41
40
|
second_cost = sys.maxsize
|
|
42
41
|
for value in range(shr_domain[MIN], shr_domain[MAX] + 1):
|
|
@@ -27,32 +27,32 @@ from nucs.solvers.choice_points import cp_put
|
|
|
27
27
|
|
|
28
28
|
@njit(cache=True)
|
|
29
29
|
def max_value_dom_heuristic(
|
|
30
|
-
params: NDArray,
|
|
31
30
|
shr_domains_stack: NDArray,
|
|
32
31
|
not_entailed_propagators_stack: NDArray,
|
|
33
32
|
dom_update_stack: NDArray,
|
|
34
33
|
stacks_top: NDArray,
|
|
35
34
|
dom_idx: int,
|
|
35
|
+
params: NDArray,
|
|
36
36
|
) -> int:
|
|
37
37
|
"""
|
|
38
38
|
Chooses the max value of the domain.
|
|
39
|
-
:param params: a two-dimensional parameters array, unused here
|
|
40
39
|
:param shr_domains_stack: the stack of shared domains
|
|
41
40
|
:param not_entailed_propagators_stack: the stack of not entailed propagators
|
|
42
41
|
:param dom_update_stack: the stack of domain updates
|
|
43
42
|
:param stacks_top: the index of the top of the stacks as a Numpy array
|
|
44
43
|
:param dom_idx: the index of the shared domain
|
|
44
|
+
:param params: a two-dimensional parameters array, unused here
|
|
45
45
|
:return: the events
|
|
46
46
|
"""
|
|
47
|
-
|
|
48
|
-
value = shr_domains_stack[
|
|
47
|
+
top = stacks_top[0]
|
|
48
|
+
value = shr_domains_stack[top, dom_idx, MAX]
|
|
49
49
|
cp_put(shr_domains_stack, not_entailed_propagators_stack, stacks_top)
|
|
50
|
-
shr_domains_stack[
|
|
51
|
-
shr_domains_stack[
|
|
52
|
-
dom_update_stack[
|
|
53
|
-
dom_update_stack[
|
|
50
|
+
shr_domains_stack[top + 1, dom_idx, MIN] = value
|
|
51
|
+
shr_domains_stack[top, dom_idx, MAX] = value - 1
|
|
52
|
+
dom_update_stack[top, DOM_UPDATE_IDX] = dom_idx
|
|
53
|
+
dom_update_stack[top, DOM_UPDATE_EVENTS] = (
|
|
54
54
|
EVENT_MASK_MAX_GROUND
|
|
55
|
-
if shr_domains_stack[
|
|
55
|
+
if shr_domains_stack[top, dom_idx, MIN] == shr_domains_stack[top, dom_idx, MAX]
|
|
56
56
|
else EVENT_MASK_MAX
|
|
57
57
|
)
|
|
58
58
|
return EVENT_MASK_MIN_GROUND
|