NUCS 2.3.0__tar.gz → 4.0.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-2.3.0 → nucs-4.0.0/NUCS.egg-info}/PKG-INFO +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/NUCS.egg-info/SOURCES.txt +30 -1
- {nucs-2.3.0/NUCS.egg-info → nucs-4.0.0}/PKG-INFO +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/docs/source/conf.py +2 -2
- {nucs-2.3.0 → nucs-4.0.0}/nucs/constants.py +33 -7
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/alpha/__main__.py +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/alpha/alpha_problem.py +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/bibd/__main__.py +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/donald/__main__.py +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/donald/donald_problem.py +1 -3
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/golomb/golomb_problem.py +21 -9
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/knapsack/__main__.py +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/magic_sequence/__main__.py +3 -2
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/magic_sequence/magic_sequence_problem.py +1 -3
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/magic_square/__main__.py +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/quasigroup/__main__.py +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/queens/__main__.py +22 -12
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/sports_tournament_scheduling/__main__.py +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/sudoku/sudoku_problem.py +2 -16
- nucs-4.0.0/nucs/examples/tsp/__main__.py +43 -0
- nucs-4.0.0/nucs/examples/tsp/total_cost_propagator.py +79 -0
- nucs-4.0.0/nucs/examples/tsp/tsp_instances.py +72 -0
- nucs-4.0.0/nucs/examples/tsp/tsp_problem.py +50 -0
- nucs-4.0.0/nucs/heuristics/first_not_instantiated_var_heuristic.py +35 -0
- nucs-4.0.0/nucs/heuristics/greatest_domain_var_heuristic.py +40 -0
- nucs-4.0.0/nucs/heuristics/heuristics.py +58 -0
- nucs-4.0.0/nucs/heuristics/max_regret_var_heuristic.py +54 -0
- nucs-4.0.0/nucs/heuristics/max_value_dom_heuristic.py +58 -0
- nucs-4.0.0/nucs/heuristics/mid_value_dom_heuristic.py +47 -0
- nucs-4.0.0/nucs/heuristics/min_cost_dom_heuristic.py +52 -0
- nucs-4.0.0/nucs/heuristics/min_value_dom_heuristic.py +58 -0
- nucs-4.0.0/nucs/heuristics/smallest_domain_var_heuristic.py +42 -0
- nucs-4.0.0/nucs/heuristics/split_low_dom_heuristic.py +58 -0
- nucs-4.0.0/nucs/heuristics/value_dom_heuristic.py +78 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/numpy_helper.py +2 -2
- nucs-4.0.0/nucs/problems/circuit_problem.py +33 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/problems/problem.py +35 -26
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/affine_eq_propagator.py +20 -31
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/affine_geq_propagator.py +32 -17
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/affine_leq_propagator.py +31 -16
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/alldifferent_propagator.py +2 -2
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/and_propagator.py +3 -3
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/count_eq_propagator.py +2 -2
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/dummy_propagator.py +2 -2
- nucs-4.0.0/nucs/propagators/element_iv_propagator.py +82 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/element_lic_propagator.py +17 -32
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/element_liv_propagator.py +16 -17
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/exactly_eq_propagator.py +2 -2
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/exactly_true_propagator.py +2 -2
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/gcc_propagator.py +2 -2
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/lexicographic_leq_propagator.py +2 -2
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/max_eq_propagator.py +2 -2
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/max_leq_propagator.py +11 -5
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/min_eq_propagator.py +2 -2
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/min_geq_propagator.py +11 -5
- nucs-4.0.0/nucs/propagators/no_sub_cycle_propagator.py +78 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/propagators.py +20 -5
- {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/relation_propagator.py +2 -2
- nucs-4.0.0/nucs/propagators/scc_propagator.py +75 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/solvers/backtrack_solver.py +99 -58
- {nucs-2.3.0 → nucs-4.0.0}/nucs/solvers/bound_consistency_algorithm.py +44 -35
- nucs-4.0.0/nucs/solvers/choice_points.py +75 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/solvers/multiprocessing_solver.py +1 -4
- nucs-4.0.0/nucs/solvers/shaving_consistency_algorithm.py +213 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/solvers/solver.py +44 -15
- {nucs-2.3.0 → nucs-4.0.0}/pyproject.toml +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_alpha.py +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_donald.py +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_knapsack.py +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_magic_sequence.py +5 -2
- {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_magic_square.py +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_quasigroup.py +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_queens.py +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_sports_tournament_scheduling.py +1 -1
- nucs-4.0.0/tests/examples/test_tsp.py +47 -0
- nucs-4.0.0/tests/heuristics/test_max_value_dom_heuristic.py +24 -0
- nucs-4.0.0/tests/heuristics/test_mid_value_dom_heuristic.py +24 -0
- nucs-4.0.0/tests/heuristics/test_min_value_dom_heuristic.py +24 -0
- nucs-4.0.0/tests/problems/__init__.py +0 -0
- nucs-4.0.0/tests/problems/test_circuit_problem.py +36 -0
- nucs-4.0.0/tests/propagators/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_affine_eq.py +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_affine_geq.py +1 -1
- {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_affine_leq.py +1 -1
- nucs-4.0.0/tests/propagators/test_element_iv.py +36 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_element_liv.py +5 -0
- nucs-4.0.0/tests/propagators/test_no_sub_cycle.py +27 -0
- nucs-4.0.0/tests/propagators/test_scc.py +32 -0
- nucs-4.0.0/tests/solvers/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/solvers/test_backtrack_solver.py +12 -2
- nucs-2.3.0/nucs/solvers/choice_points.py +0 -84
- nucs-2.3.0/nucs/solvers/heuristics.py +0 -165
- nucs-2.3.0/nucs/solvers/shaving_consistency_algorithm.py +0 -274
- {nucs-2.3.0 → nucs-4.0.0}/LICENSE.md +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/NUCS.egg-info/dependency_links.txt +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/NUCS.egg-info/requires.txt +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/NUCS.egg-info/top_level.txt +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/README.md +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/alpha/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/bibd/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/bibd/bibd_problem.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/donald/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/golomb/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/golomb/__main__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/knapsack/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/knapsack/knapsack_problem.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/magic_sequence/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/magic_square/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/magic_square/magic_square_problem.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/quasigroup/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/quasigroup/quasigroup_problem.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/queens/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/queens/queens_problem.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/schur_lemma/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/schur_lemma/__main__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/schur_lemma/schur_lemma_problem.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/sports_tournament_scheduling/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/sports_tournament_scheduling/sports_tournament_scheduling_problem.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/sudoku/__init__.py +0 -0
- {nucs-2.3.0/nucs/problems → nucs-4.0.0/nucs/examples/tsp}/__init__.py +0 -0
- {nucs-2.3.0/nucs/propagators → nucs-4.0.0/nucs/heuristics}/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/numba_helper.py +0 -0
- {nucs-2.3.0/nucs/solvers → nucs-4.0.0/nucs/problems}/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/problems/latin_square_problem.py +0 -0
- {nucs-2.3.0/tests → nucs-4.0.0/nucs/propagators}/__init__.py +0 -0
- {nucs-2.3.0/tests/problems → nucs-4.0.0/nucs/solvers}/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/nucs/solvers/consistency_algorithms.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/setup.cfg +0 -0
- {nucs-2.3.0/tests/propagators → nucs-4.0.0/tests}/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_bibd.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_golomb.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_latin_square.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_schur_lemma.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_sudokus.py +0 -0
- {nucs-2.3.0/tests/solvers → nucs-4.0.0/tests/heuristics}/__init__.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/problems/test_problem.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_alldifferent.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_count_eq.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_element_lic.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_exactly_eq.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_gcc.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_lexicographic_leq.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_max_eq.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_max_leq.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_min_eq.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_min_geq.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_relation.py +0 -0
- {nucs-2.3.0 → nucs-4.0.0}/tests/solvers/test_multiprocessing_solver.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: NUCS
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.0.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
|
|
@@ -47,7 +47,25 @@ nucs/examples/sports_tournament_scheduling/__main__.py
|
|
|
47
47
|
nucs/examples/sports_tournament_scheduling/sports_tournament_scheduling_problem.py
|
|
48
48
|
nucs/examples/sudoku/__init__.py
|
|
49
49
|
nucs/examples/sudoku/sudoku_problem.py
|
|
50
|
+
nucs/examples/tsp/__init__.py
|
|
51
|
+
nucs/examples/tsp/__main__.py
|
|
52
|
+
nucs/examples/tsp/total_cost_propagator.py
|
|
53
|
+
nucs/examples/tsp/tsp_instances.py
|
|
54
|
+
nucs/examples/tsp/tsp_problem.py
|
|
55
|
+
nucs/heuristics/__init__.py
|
|
56
|
+
nucs/heuristics/first_not_instantiated_var_heuristic.py
|
|
57
|
+
nucs/heuristics/greatest_domain_var_heuristic.py
|
|
58
|
+
nucs/heuristics/heuristics.py
|
|
59
|
+
nucs/heuristics/max_regret_var_heuristic.py
|
|
60
|
+
nucs/heuristics/max_value_dom_heuristic.py
|
|
61
|
+
nucs/heuristics/mid_value_dom_heuristic.py
|
|
62
|
+
nucs/heuristics/min_cost_dom_heuristic.py
|
|
63
|
+
nucs/heuristics/min_value_dom_heuristic.py
|
|
64
|
+
nucs/heuristics/smallest_domain_var_heuristic.py
|
|
65
|
+
nucs/heuristics/split_low_dom_heuristic.py
|
|
66
|
+
nucs/heuristics/value_dom_heuristic.py
|
|
50
67
|
nucs/problems/__init__.py
|
|
68
|
+
nucs/problems/circuit_problem.py
|
|
51
69
|
nucs/problems/latin_square_problem.py
|
|
52
70
|
nucs/problems/problem.py
|
|
53
71
|
nucs/propagators/__init__.py
|
|
@@ -58,6 +76,7 @@ nucs/propagators/alldifferent_propagator.py
|
|
|
58
76
|
nucs/propagators/and_propagator.py
|
|
59
77
|
nucs/propagators/count_eq_propagator.py
|
|
60
78
|
nucs/propagators/dummy_propagator.py
|
|
79
|
+
nucs/propagators/element_iv_propagator.py
|
|
61
80
|
nucs/propagators/element_lic_propagator.py
|
|
62
81
|
nucs/propagators/element_liv_propagator.py
|
|
63
82
|
nucs/propagators/exactly_eq_propagator.py
|
|
@@ -68,14 +87,15 @@ nucs/propagators/max_eq_propagator.py
|
|
|
68
87
|
nucs/propagators/max_leq_propagator.py
|
|
69
88
|
nucs/propagators/min_eq_propagator.py
|
|
70
89
|
nucs/propagators/min_geq_propagator.py
|
|
90
|
+
nucs/propagators/no_sub_cycle_propagator.py
|
|
71
91
|
nucs/propagators/propagators.py
|
|
72
92
|
nucs/propagators/relation_propagator.py
|
|
93
|
+
nucs/propagators/scc_propagator.py
|
|
73
94
|
nucs/solvers/__init__.py
|
|
74
95
|
nucs/solvers/backtrack_solver.py
|
|
75
96
|
nucs/solvers/bound_consistency_algorithm.py
|
|
76
97
|
nucs/solvers/choice_points.py
|
|
77
98
|
nucs/solvers/consistency_algorithms.py
|
|
78
|
-
nucs/solvers/heuristics.py
|
|
79
99
|
nucs/solvers/multiprocessing_solver.py
|
|
80
100
|
nucs/solvers/shaving_consistency_algorithm.py
|
|
81
101
|
nucs/solvers/solver.py
|
|
@@ -93,7 +113,13 @@ tests/examples/test_queens.py
|
|
|
93
113
|
tests/examples/test_schur_lemma.py
|
|
94
114
|
tests/examples/test_sports_tournament_scheduling.py
|
|
95
115
|
tests/examples/test_sudokus.py
|
|
116
|
+
tests/examples/test_tsp.py
|
|
117
|
+
tests/heuristics/__init__.py
|
|
118
|
+
tests/heuristics/test_max_value_dom_heuristic.py
|
|
119
|
+
tests/heuristics/test_mid_value_dom_heuristic.py
|
|
120
|
+
tests/heuristics/test_min_value_dom_heuristic.py
|
|
96
121
|
tests/problems/__init__.py
|
|
122
|
+
tests/problems/test_circuit_problem.py
|
|
97
123
|
tests/problems/test_problem.py
|
|
98
124
|
tests/propagators/__init__.py
|
|
99
125
|
tests/propagators/test_affine_eq.py
|
|
@@ -101,6 +127,7 @@ tests/propagators/test_affine_geq.py
|
|
|
101
127
|
tests/propagators/test_affine_leq.py
|
|
102
128
|
tests/propagators/test_alldifferent.py
|
|
103
129
|
tests/propagators/test_count_eq.py
|
|
130
|
+
tests/propagators/test_element_iv.py
|
|
104
131
|
tests/propagators/test_element_lic.py
|
|
105
132
|
tests/propagators/test_element_liv.py
|
|
106
133
|
tests/propagators/test_exactly_eq.py
|
|
@@ -110,7 +137,9 @@ tests/propagators/test_max_eq.py
|
|
|
110
137
|
tests/propagators/test_max_leq.py
|
|
111
138
|
tests/propagators/test_min_eq.py
|
|
112
139
|
tests/propagators/test_min_geq.py
|
|
140
|
+
tests/propagators/test_no_sub_cycle.py
|
|
113
141
|
tests/propagators/test_relation.py
|
|
142
|
+
tests/propagators/test_scc.py
|
|
114
143
|
tests/solvers/__init__.py
|
|
115
144
|
tests/solvers/test_backtrack_solver.py
|
|
116
145
|
tests/solvers/test_multiprocessing_solver.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: NUCS
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.0.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,12 +14,24 @@ import os
|
|
|
14
14
|
|
|
15
15
|
from numba import bool, int32, int64, types, uint8, uint16 # type: ignore
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
RG_START = 0 # index corresponding the start of a values range
|
|
18
|
+
RG_END = 1 # index corresponding the end of a values range
|
|
19
19
|
|
|
20
20
|
MIN = 0 # min value of a domain
|
|
21
21
|
MAX = 1 # max value of a domain
|
|
22
22
|
|
|
23
|
+
DOM_UPDATE_IDX = 0
|
|
24
|
+
DOM_UPDATE_EVENTS = 1
|
|
25
|
+
|
|
26
|
+
EVENT_MASK_MIN = 1 << 0
|
|
27
|
+
EVENT_MASK_MAX = 1 << 1
|
|
28
|
+
EVENT_MASK_GROUND = 1 << 2
|
|
29
|
+
EVENT_MASK_MIN_MAX = EVENT_MASK_MIN | EVENT_MASK_MAX
|
|
30
|
+
EVENT_MASK_MIN_GROUND = EVENT_MASK_MIN | EVENT_MASK_GROUND
|
|
31
|
+
EVENT_MASK_MAX_GROUND = EVENT_MASK_MAX | EVENT_MASK_GROUND
|
|
32
|
+
EVENT_MASK_MIN_MAX_GROUND = EVENT_MASK_MIN | EVENT_MASK_MAX | EVENT_MASK_GROUND
|
|
33
|
+
|
|
34
|
+
|
|
23
35
|
PROP_INCONSISTENCY = 0 # returned by a propagator when inconsistent
|
|
24
36
|
PROP_CONSISTENCY = 1 # returned by a propagator when consistent
|
|
25
37
|
PROP_ENTAILMENT = 2 # returned by a propagator when entailed
|
|
@@ -29,8 +41,6 @@ PROBLEM_UNBOUND = 1 # returned when the filtering of a problem has been complet
|
|
|
29
41
|
PROBLEM_BOUND = 2 # returned when a problem is solved
|
|
30
42
|
|
|
31
43
|
SIGNATURE_COMPUTE_DOMAINS = int64(int32[:, :], int32[:]) # domains, parameters
|
|
32
|
-
SIGNATURE_DOM_HEURISTIC = int64(int32[:], int32[:]) # shr_domain, shr_domain_copy
|
|
33
|
-
SIGNATURE_VAR_HEURISTIC = int64(int32[:, :]) # shr_domains
|
|
34
44
|
SIGNATURE_CONSISTENCY_ALG = int64(
|
|
35
45
|
int64[:], # statistics
|
|
36
46
|
uint8[:], # algorithms
|
|
@@ -41,14 +51,30 @@ SIGNATURE_CONSISTENCY_ALG = int64(
|
|
|
41
51
|
uint16[:], # props_dom_indices
|
|
42
52
|
int32[:, :], # props_dom_offsets
|
|
43
53
|
int32[:], # props_parameters
|
|
44
|
-
|
|
54
|
+
uint8[:, :], # shr_domains_propagators
|
|
45
55
|
int32[:, :, :], # shr_domains_stack
|
|
46
56
|
bool[:, :], # not_entailed_propagators_stack
|
|
47
57
|
uint16[:, :], # dom_update_stack
|
|
48
|
-
uint8[:], #
|
|
58
|
+
uint8[:], # stacks_top
|
|
49
59
|
bool[:], # triggered_propagators
|
|
50
60
|
int64[:], # compute_domains_addrs
|
|
61
|
+
uint16[:], # decision_domains
|
|
62
|
+
)
|
|
63
|
+
SIGNATURE_DOM_HEURISTIC = int64(
|
|
64
|
+
int64[:, :], # dom_heuristic_params
|
|
65
|
+
int32[:, :, :], # shr_domains_stack
|
|
66
|
+
bool[:, :], # not_entailed_propagators_stack
|
|
67
|
+
uint16[:, :], # dom_update_stack
|
|
68
|
+
uint8[:], # stacks_top
|
|
69
|
+
int64, # dom_idx
|
|
51
70
|
)
|
|
71
|
+
SIGNATURE_VAR_HEURISTIC = int64(
|
|
72
|
+
int64[:, :], # var_heuristic_params
|
|
73
|
+
uint16[:], # decision_variables
|
|
74
|
+
int32[:, :, :], # shr_domains_stack
|
|
75
|
+
uint8[:], # stacks_top
|
|
76
|
+
)
|
|
77
|
+
|
|
52
78
|
|
|
53
79
|
TYPE_COMPUTE_DOMAINS = types.FunctionType(SIGNATURE_COMPUTE_DOMAINS)
|
|
54
80
|
TYPE_DOM_HEURISTIC = types.FunctionType(SIGNATURE_DOM_HEURISTIC)
|
|
@@ -57,7 +83,7 @@ TYPE_CONSISTENCY_ALG = types.FunctionType(SIGNATURE_CONSISTENCY_ALG)
|
|
|
57
83
|
|
|
58
84
|
NUMBA_DISABLE_JIT = os.getenv("NUMBA_DISABLE_JIT")
|
|
59
85
|
|
|
60
|
-
LOG_FORMAT = "%(asctime)s
|
|
86
|
+
LOG_FORMAT = "[ %(asctime)s | %(processName)s | %(levelname)s ] %(name)s.%(funcName)s - %(message)s"
|
|
61
87
|
LOG_LEVEL_DEBUG = "DEBUG"
|
|
62
88
|
LOG_LEVEL_INFO = "INFO"
|
|
63
89
|
LOG_LEVEL_WARNING = "WARNING"
|
|
@@ -16,8 +16,8 @@ from rich import print
|
|
|
16
16
|
|
|
17
17
|
from nucs.constants import LOG_LEVEL_INFO, LOG_LEVELS
|
|
18
18
|
from nucs.examples.alpha.alpha_problem import AlphaProblem
|
|
19
|
+
from nucs.heuristics.heuristics import DOM_HEURISTIC_MIN_VALUE, VAR_HEURISTIC_SMALLEST_DOMAIN
|
|
19
20
|
from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
20
|
-
from nucs.solvers.heuristics import DOM_HEURISTIC_MIN_VALUE, VAR_HEURISTIC_SMALLEST_DOMAIN
|
|
21
21
|
|
|
22
22
|
# Run with the following command (the second run is much faster because the code has been compiled):
|
|
23
23
|
# NUMBA_CACHE_DIR=.numba/cache python -m nucs.examples.alpha
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
###############################################################################
|
|
13
13
|
from typing import Dict
|
|
14
14
|
|
|
15
|
-
from numpy.
|
|
15
|
+
from numpy.typing import NDArray
|
|
16
16
|
|
|
17
17
|
from nucs.problems.problem import Problem
|
|
18
18
|
from nucs.propagators.propagators import ALG_AFFINE_EQ, ALG_ALLDIFFERENT
|
|
@@ -16,8 +16,8 @@ from rich import print
|
|
|
16
16
|
|
|
17
17
|
from nucs.constants import LOG_LEVEL_INFO, LOG_LEVELS
|
|
18
18
|
from nucs.examples.bibd.bibd_problem import BIBDProblem
|
|
19
|
+
from nucs.heuristics.heuristics import DOM_HEURISTIC_MAX_VALUE
|
|
19
20
|
from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
20
|
-
from nucs.solvers.heuristics import DOM_HEURISTIC_MAX_VALUE
|
|
21
21
|
|
|
22
22
|
# Run with the following command (the second run is much faster because the code has been compiled):
|
|
23
23
|
# NUMBA_CACHE_DIR=.numba/cache python -m nucs.examples.bibd -v 8 -b 14 -r 7 -k 4 -l 3 --symmetry_breaking
|
|
@@ -16,8 +16,8 @@ from rich import print
|
|
|
16
16
|
|
|
17
17
|
from nucs.constants import LOG_LEVEL_INFO, LOG_LEVELS
|
|
18
18
|
from nucs.examples.donald.donald_problem import DonaldProblem
|
|
19
|
+
from nucs.heuristics.heuristics import DOM_HEURISTIC_MIN_VALUE, VAR_HEURISTIC_SMALLEST_DOMAIN
|
|
19
20
|
from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
20
|
-
from nucs.solvers.heuristics import DOM_HEURISTIC_MIN_VALUE, VAR_HEURISTIC_SMALLEST_DOMAIN
|
|
21
21
|
|
|
22
22
|
# Run with the following command (the second run is much faster because the code has been compiled):
|
|
23
23
|
# NUMBA_CACHE_DIR=.numba/cache python -m nucs.examples.donald
|
|
@@ -38,9 +38,7 @@ class DonaldProblem(Problem):
|
|
|
38
38
|
[200, -1000, 100002, 9900, 100000, 20, 1000, 0, -99010, -1, 0],
|
|
39
39
|
)
|
|
40
40
|
)
|
|
41
|
-
self.add_propagator(
|
|
42
|
-
([A, B, D, E, G, L, N, O, R, T], ALG_ALLDIFFERENT, []),
|
|
43
|
-
)
|
|
41
|
+
self.add_propagator(([A, B, D, E, G, L, N, O, R, T], ALG_ALLDIFFERENT, []))
|
|
44
42
|
|
|
45
43
|
def solution_as_dict(self, solution: NDArray) -> Dict[str, int]:
|
|
46
44
|
"""
|
|
@@ -16,11 +16,11 @@ import numpy as np
|
|
|
16
16
|
from numba import njit # type: ignore
|
|
17
17
|
from numpy.typing import NDArray
|
|
18
18
|
|
|
19
|
-
from nucs.constants import MAX, MIN
|
|
19
|
+
from nucs.constants import EVENT_MASK_GROUND, EVENT_MASK_MIN, MAX, MIN
|
|
20
|
+
from nucs.heuristics.heuristics import first_not_instantiated_var_heuristic
|
|
20
21
|
from nucs.problems.problem import Problem
|
|
21
22
|
from nucs.propagators.propagators import ALG_AFFINE_EQ, ALG_AFFINE_LEQ, ALG_ALLDIFFERENT, add_propagators
|
|
22
23
|
from nucs.solvers.bound_consistency_algorithm import bound_consistency_algorithm
|
|
23
|
-
from nucs.solvers.heuristics import first_not_instantiated_var_heuristic
|
|
24
24
|
|
|
25
25
|
GOLOMB_LENGTHS = np.array([0, 0, 1, 3, 6, 11, 17, 25, 34, 44, 55, 72, 85, 106, 127])
|
|
26
26
|
|
|
@@ -90,7 +90,7 @@ class GolombProblem(Problem):
|
|
|
90
90
|
[1, -1, -1, 0],
|
|
91
91
|
)
|
|
92
92
|
)
|
|
93
|
-
self.add_propagator((list(range(self.
|
|
93
|
+
self.add_propagator((list(range(self.shr_domain_nb)), ALG_ALLDIFFERENT, []))
|
|
94
94
|
# redundant constraints
|
|
95
95
|
for i in range(mark_nb - 1):
|
|
96
96
|
for j in range(i + 1, mark_nb):
|
|
@@ -127,9 +127,10 @@ def golomb_consistency_algorithm(
|
|
|
127
127
|
shr_domains_stack: NDArray,
|
|
128
128
|
not_entailed_propagators_stack: NDArray,
|
|
129
129
|
dom_update_stack: NDArray,
|
|
130
|
-
|
|
130
|
+
stacks_top: NDArray,
|
|
131
131
|
triggered_propagators: NDArray,
|
|
132
132
|
compute_domains_addrs: NDArray,
|
|
133
|
+
decision_domains: NDArray,
|
|
133
134
|
) -> int:
|
|
134
135
|
"""
|
|
135
136
|
Applies a custom consistency algorithm for the Golomb Ruler problem.
|
|
@@ -137,9 +138,12 @@ def golomb_consistency_algorithm(
|
|
|
137
138
|
:param problem: the problem
|
|
138
139
|
:return: the status as an int
|
|
139
140
|
"""
|
|
141
|
+
top = stacks_top[0]
|
|
140
142
|
# first prune the search space
|
|
141
143
|
mark_nb = (1 + int(math.sqrt(8 * len(dom_indices_arr) + 1))) // 2
|
|
142
|
-
ni_var_idx = first_not_instantiated_var_heuristic(
|
|
144
|
+
ni_var_idx = first_not_instantiated_var_heuristic(
|
|
145
|
+
None, decision_domains, shr_domains_stack, stacks_top
|
|
146
|
+
) # no domains shared between vars
|
|
143
147
|
if 1 < ni_var_idx < mark_nb - 1: # otherwise useless
|
|
144
148
|
used_distance = np.zeros(sum_first(mark_nb - 2) + 1, dtype=np.bool)
|
|
145
149
|
# a reusable array for storing the minimal sum of different integers:
|
|
@@ -148,7 +152,7 @@ def golomb_consistency_algorithm(
|
|
|
148
152
|
# the following will mark at most sum(n-3) numbers as used
|
|
149
153
|
# hence there will be at least n-2 unused numbers greater than 0
|
|
150
154
|
for var_idx in range(index(mark_nb, ni_var_idx - 2, ni_var_idx - 1) + 1):
|
|
151
|
-
dist = shr_domains_stack[
|
|
155
|
+
dist = shr_domains_stack[top, dom_indices_arr[var_idx], MIN] # no offset
|
|
152
156
|
if dist < len(used_distance):
|
|
153
157
|
used_distance[dist] = True
|
|
154
158
|
# let's compute the sum of non-used numbers
|
|
@@ -161,9 +165,16 @@ def golomb_consistency_algorithm(
|
|
|
161
165
|
for i in range(ni_var_idx - 1, mark_nb - 1):
|
|
162
166
|
for j in range(i + 1, mark_nb):
|
|
163
167
|
dom_idx = dom_indices_arr[index(mark_nb, i, j)]
|
|
164
|
-
shr_domains_stack[
|
|
168
|
+
shr_domains_stack[top, dom_idx, MIN] = minimal_sum[j - i] # no offset
|
|
169
|
+
events = EVENT_MASK_MIN
|
|
170
|
+
if shr_domains_stack[top, dom_idx, MIN] == shr_domains_stack[top, dom_idx, MAX]:
|
|
171
|
+
events |= EVENT_MASK_GROUND
|
|
165
172
|
add_propagators(
|
|
166
|
-
triggered_propagators,
|
|
173
|
+
triggered_propagators,
|
|
174
|
+
not_entailed_propagators_stack[top],
|
|
175
|
+
shr_domains_propagators,
|
|
176
|
+
dom_idx,
|
|
177
|
+
events,
|
|
167
178
|
)
|
|
168
179
|
return bound_consistency_algorithm(
|
|
169
180
|
statistics,
|
|
@@ -179,7 +190,8 @@ def golomb_consistency_algorithm(
|
|
|
179
190
|
shr_domains_stack,
|
|
180
191
|
not_entailed_propagators_stack,
|
|
181
192
|
dom_update_stack,
|
|
182
|
-
|
|
193
|
+
stacks_top,
|
|
183
194
|
triggered_propagators,
|
|
184
195
|
compute_domains_addrs,
|
|
196
|
+
decision_domains,
|
|
185
197
|
)
|
|
@@ -16,8 +16,8 @@ from rich import print
|
|
|
16
16
|
|
|
17
17
|
from nucs.constants import LOG_LEVEL_INFO, LOG_LEVELS
|
|
18
18
|
from nucs.examples.knapsack.knapsack_problem import KnapsackProblem
|
|
19
|
+
from nucs.heuristics.heuristics import DOM_HEURISTIC_MAX_VALUE, VAR_HEURISTIC_FIRST_NOT_INSTANTIATED
|
|
19
20
|
from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
20
|
-
from nucs.solvers.heuristics import DOM_HEURISTIC_MAX_VALUE, VAR_HEURISTIC_FIRST_NOT_INSTANTIATED
|
|
21
21
|
|
|
22
22
|
# Run with the following command (the second run is much faster because the code has been compiled):
|
|
23
23
|
# NUMBA_CACHE_DIR=.numba/cache python -m nucs.examples.knapsack
|
|
@@ -16,8 +16,8 @@ from rich import print
|
|
|
16
16
|
|
|
17
17
|
from nucs.constants import LOG_LEVEL_INFO, LOG_LEVELS
|
|
18
18
|
from nucs.examples.magic_sequence.magic_sequence_problem import MagicSequenceProblem
|
|
19
|
+
from nucs.heuristics.heuristics import DOM_HEURISTIC_MIN_VALUE, VAR_HEURISTIC_FIRST_NOT_INSTANTIATED
|
|
19
20
|
from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
20
|
-
from nucs.solvers.heuristics import DOM_HEURISTIC_MIN_VALUE, VAR_HEURISTIC_LAST_NOT_INSTANTIATED
|
|
21
21
|
|
|
22
22
|
# Run with the following command (the second run is much faster because the code has been compiled):
|
|
23
23
|
# NUMBA_CACHE_DIR=.numba/cache python -m nucs.examples.magic_sequence -n 100
|
|
@@ -29,7 +29,8 @@ if __name__ == "__main__":
|
|
|
29
29
|
problem = MagicSequenceProblem(args.n)
|
|
30
30
|
solver = BacktrackSolver(
|
|
31
31
|
problem,
|
|
32
|
-
|
|
32
|
+
decision_domains=list(range(args.n - 1, -1, -1)),
|
|
33
|
+
var_heuristic_idx=VAR_HEURISTIC_FIRST_NOT_INSTANTIATED,
|
|
33
34
|
dom_heuristic_idx=DOM_HEURISTIC_MIN_VALUE,
|
|
34
35
|
log_level=args.log_level,
|
|
35
36
|
)
|
|
@@ -16,8 +16,7 @@ from nucs.propagators.propagators import ALG_AFFINE_EQ, ALG_COUNT_EQ
|
|
|
16
16
|
|
|
17
17
|
class MagicSequenceProblem(Problem):
|
|
18
18
|
"""
|
|
19
|
-
Find a sequence x_0, ... x_n-1
|
|
20
|
-
such that each x_i is the number of occurences of i in the sequence.
|
|
19
|
+
Find a sequence x_0, ... x_n-1 such that each x_i is the number of occurrences of i in the sequence.
|
|
21
20
|
|
|
22
21
|
CSPLIB problem #19 - https://www.csplib.org/Problems/prob019/
|
|
23
22
|
"""
|
|
@@ -27,7 +26,6 @@ class MagicSequenceProblem(Problem):
|
|
|
27
26
|
Inits the problem.
|
|
28
27
|
:param n: the size of the sequence
|
|
29
28
|
"""
|
|
30
|
-
self.n = n
|
|
31
29
|
super().__init__([(0, n)] * n)
|
|
32
30
|
for i in range(n):
|
|
33
31
|
self.add_propagator((list(range(n)) + [i], ALG_COUNT_EQ, [i]))
|
|
@@ -16,8 +16,8 @@ from rich import print
|
|
|
16
16
|
|
|
17
17
|
from nucs.constants import LOG_LEVEL_INFO, LOG_LEVELS
|
|
18
18
|
from nucs.examples.magic_square.magic_square_problem import MagicSquareProblem
|
|
19
|
+
from nucs.heuristics.heuristics import DOM_HEURISTIC_MAX_VALUE, VAR_HEURISTIC_SMALLEST_DOMAIN
|
|
19
20
|
from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
20
|
-
from nucs.solvers.heuristics import DOM_HEURISTIC_MAX_VALUE, VAR_HEURISTIC_SMALLEST_DOMAIN
|
|
21
21
|
|
|
22
22
|
# Run with the following command (the second run is much faster because the code has been compiled):
|
|
23
23
|
# NUMBA_CACHE_DIR=.numba/cache python -m nucs.examples.magic_square -n 4 --symmetry_breaking
|
|
@@ -16,8 +16,8 @@ from rich import print
|
|
|
16
16
|
|
|
17
17
|
from nucs.constants import LOG_LEVEL_INFO, LOG_LEVELS
|
|
18
18
|
from nucs.examples.quasigroup.quasigroup_problem import Quasigroup5Problem
|
|
19
|
+
from nucs.heuristics.heuristics import DOM_HEURISTIC_MIN_VALUE, VAR_HEURISTIC_SMALLEST_DOMAIN
|
|
19
20
|
from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
20
|
-
from nucs.solvers.heuristics import DOM_HEURISTIC_MIN_VALUE, VAR_HEURISTIC_SMALLEST_DOMAIN
|
|
21
21
|
|
|
22
22
|
# Run with the following command (the second run is much faster because the code has been compiled):
|
|
23
23
|
# NUMBA_CACHE_DIR=.numba/cache python -m nucs.examples.quasigroup -n 10 --symmetry_breaking
|
|
@@ -16,9 +16,9 @@ from rich import print
|
|
|
16
16
|
|
|
17
17
|
from nucs.constants import LOG_LEVEL_INFO, LOG_LEVELS
|
|
18
18
|
from nucs.examples.queens.queens_problem import QueensProblem
|
|
19
|
+
from nucs.heuristics.heuristics import VAR_HEURISTIC_FIRST_NOT_INSTANTIATED, VAR_HEURISTIC_SMALLEST_DOMAIN
|
|
19
20
|
from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
20
21
|
from nucs.solvers.consistency_algorithms import CONSISTENCY_ALG_BC, CONSISTENCY_ALG_SHAVING
|
|
21
|
-
from nucs.solvers.heuristics import VAR_HEURISTIC_FIRST_NOT_INSTANTIATED, VAR_HEURISTIC_SMALLEST_DOMAIN
|
|
22
22
|
from nucs.solvers.multiprocessing_solver import MultiprocessingSolver
|
|
23
23
|
|
|
24
24
|
# Run with the following command (the second run is much faster because the code has been compiled):
|
|
@@ -32,17 +32,27 @@ if __name__ == "__main__":
|
|
|
32
32
|
parser.add_argument("--ff", type=bool, action=argparse.BooleanOptionalAction, default=False)
|
|
33
33
|
args = parser.parse_args()
|
|
34
34
|
problem = QueensProblem(args.n)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
35
|
+
solver = (
|
|
36
|
+
MultiprocessingSolver(
|
|
37
|
+
[
|
|
38
|
+
BacktrackSolver(
|
|
39
|
+
problem,
|
|
40
|
+
consistency_alg_idx=CONSISTENCY_ALG_SHAVING if args.shaving else CONSISTENCY_ALG_BC,
|
|
41
|
+
var_heuristic_idx=(
|
|
42
|
+
VAR_HEURISTIC_SMALLEST_DOMAIN if args.ff else VAR_HEURISTIC_FIRST_NOT_INSTANTIATED
|
|
43
|
+
),
|
|
44
|
+
log_level=args.log_level,
|
|
45
|
+
)
|
|
46
|
+
for problem in problem.split(args.processors, 0)
|
|
47
|
+
]
|
|
48
|
+
)
|
|
49
|
+
if args.processors > 1
|
|
50
|
+
else BacktrackSolver(
|
|
51
|
+
problem,
|
|
52
|
+
consistency_alg_idx=CONSISTENCY_ALG_SHAVING if args.shaving else CONSISTENCY_ALG_BC,
|
|
53
|
+
var_heuristic_idx=VAR_HEURISTIC_SMALLEST_DOMAIN if args.ff else VAR_HEURISTIC_FIRST_NOT_INSTANTIATED,
|
|
54
|
+
log_level=args.log_level,
|
|
55
|
+
)
|
|
46
56
|
)
|
|
47
57
|
solver.solve_all()
|
|
48
58
|
print(solver.get_statistics())
|
|
@@ -18,8 +18,8 @@ from nucs.constants import LOG_LEVEL_INFO, LOG_LEVELS
|
|
|
18
18
|
from nucs.examples.sports_tournament_scheduling.sports_tournament_scheduling_problem import (
|
|
19
19
|
SportsTournamentSchedulingProblem,
|
|
20
20
|
)
|
|
21
|
+
from nucs.heuristics.heuristics import DOM_HEURISTIC_MIN_VALUE, VAR_HEURISTIC_SMALLEST_DOMAIN
|
|
21
22
|
from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
22
|
-
from nucs.solvers.heuristics import DOM_HEURISTIC_MIN_VALUE, VAR_HEURISTIC_SMALLEST_DOMAIN
|
|
23
23
|
|
|
24
24
|
# Run with the following command (the second run is much faster because the code has been compiled):
|
|
25
25
|
# NUMBA_CACHE_DIR=.numba/cache python -m nucs.examples.sports_tournament_scheduling -n 8
|
|
@@ -29,21 +29,7 @@ class SudokuProblem(LatinSquareProblem):
|
|
|
29
29
|
super().__init__(list(range(1, 10)), givens)
|
|
30
30
|
for i in range(3):
|
|
31
31
|
for j in range(3):
|
|
32
|
-
|
|
32
|
+
o = i * 27 + j * 3
|
|
33
33
|
self.add_propagator(
|
|
34
|
-
(
|
|
35
|
-
[
|
|
36
|
-
0 + offset,
|
|
37
|
-
1 + offset,
|
|
38
|
-
2 + offset,
|
|
39
|
-
9 + offset,
|
|
40
|
-
10 + offset,
|
|
41
|
-
11 + offset,
|
|
42
|
-
18 + offset,
|
|
43
|
-
19 + offset,
|
|
44
|
-
20 + offset,
|
|
45
|
-
],
|
|
46
|
-
ALG_ALLDIFFERENT,
|
|
47
|
-
[],
|
|
48
|
-
)
|
|
34
|
+
([0 + o, 1 + o, 2 + o, 9 + o, 10 + o, 11 + o, 18 + o, 19 + o, 20 + o], ALG_ALLDIFFERENT, [])
|
|
49
35
|
)
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
|
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
|
+
|
|
22
|
+
# Run with the following command (the second run is much faster because the code has been compiled):
|
|
23
|
+
# NUMBA_CACHE_DIR=.numba/cache python -m nucs.examples.alpha
|
|
24
|
+
if __name__ == "__main__":
|
|
25
|
+
parser = argparse.ArgumentParser()
|
|
26
|
+
parser.add_argument("--log_level", choices=LOG_LEVELS, default=LOG_LEVEL_INFO)
|
|
27
|
+
parser.add_argument("--name", choices=["GR17", "GR21", "GR24"], default="GR17")
|
|
28
|
+
parser.add_argument("--shaving", type=bool, action=argparse.BooleanOptionalAction, default=False)
|
|
29
|
+
args = parser.parse_args()
|
|
30
|
+
tsp_instance = TSP_INSTANCES[args.name]
|
|
31
|
+
problem = TSPProblem(tsp_instance)
|
|
32
|
+
solver = BacktrackSolver(
|
|
33
|
+
problem,
|
|
34
|
+
consistency_alg_idx=CONSISTENCY_ALG_SHAVING if args.shaving else CONSISTENCY_ALG_BC,
|
|
35
|
+
decision_domains=list(range(len(tsp_instance))),
|
|
36
|
+
var_heuristic_idx=VAR_HEURISTIC_MAX_REGRET,
|
|
37
|
+
var_heuristic_params=tsp_instance,
|
|
38
|
+
dom_heuristic_idx=DOM_HEURISTIC_MIN_COST,
|
|
39
|
+
dom_heuristic_params=tsp_instance,
|
|
40
|
+
log_level=args.log_level,
|
|
41
|
+
)
|
|
42
|
+
solution = solver.minimize(problem.shr_domain_nb - 1)
|
|
43
|
+
print(solver.get_statistics())
|
|
@@ -0,0 +1,79 @@
|
|
|
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 EVENT_MASK_MIN_MAX, MAX, MIN, PROP_CONSISTENCY, PROP_INCONSISTENCY
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_complexity_total_cost(n: int, parameters: NDArray) -> float:
|
|
23
|
+
"""
|
|
24
|
+
Returns the time complexity of the propagator as a float.
|
|
25
|
+
:param n: the number of variables
|
|
26
|
+
:param parameters: the parameters, unused here
|
|
27
|
+
:return: a float
|
|
28
|
+
"""
|
|
29
|
+
return 2 * n
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_triggers_total_cost(n: int, parameters: NDArray) -> NDArray:
|
|
33
|
+
"""
|
|
34
|
+
This propagator is triggered whenever there is a change in the domain of a variable.
|
|
35
|
+
:param n: the number of variables
|
|
36
|
+
:param parameters: the parameters, unused here
|
|
37
|
+
:return: an array of triggers
|
|
38
|
+
"""
|
|
39
|
+
triggers = np.full(n, dtype=np.uint8, fill_value=EVENT_MASK_MIN_MAX)
|
|
40
|
+
triggers[-1] = 0
|
|
41
|
+
return triggers
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@njit(cache=True)
|
|
45
|
+
def compute_domains_total_cost(domains: NDArray, parameters: NDArray) -> int:
|
|
46
|
+
"""
|
|
47
|
+
:param domains: the domains of the variables
|
|
48
|
+
:param parameters: the parameters of the propagator
|
|
49
|
+
:return: the status of the propagation (consistency, inconsistency or entailment) as an int
|
|
50
|
+
"""
|
|
51
|
+
n = len(domains) - 1
|
|
52
|
+
used = np.zeros(n, dtype=np.bool)
|
|
53
|
+
for i in range(n):
|
|
54
|
+
if domains[i, MIN] == domains[i, MAX]:
|
|
55
|
+
used[domains[i, MIN]] = True
|
|
56
|
+
global_min = global_max = 0
|
|
57
|
+
for i in range(n):
|
|
58
|
+
local_min = sys.maxsize
|
|
59
|
+
local_max = 0
|
|
60
|
+
if domains[i, MIN] == domains[i, MAX]:
|
|
61
|
+
local_min = local_max = parameters[i * n + domains[i, MIN]]
|
|
62
|
+
else:
|
|
63
|
+
for value in range(domains[i, MIN], domains[i, MAX] + 1):
|
|
64
|
+
if not used[value]:
|
|
65
|
+
cost = parameters[i * n + value]
|
|
66
|
+
if cost > 0:
|
|
67
|
+
if cost < local_min:
|
|
68
|
+
local_min = cost
|
|
69
|
+
if cost > local_max:
|
|
70
|
+
local_max = cost
|
|
71
|
+
if local_min > local_max:
|
|
72
|
+
return PROP_INCONSISTENCY
|
|
73
|
+
global_min += local_min
|
|
74
|
+
global_max += local_max
|
|
75
|
+
domains[-1, MIN] = max(domains[-1, MIN], global_min)
|
|
76
|
+
domains[-1, MAX] = min(domains[-1, MAX], global_max)
|
|
77
|
+
if domains[-1, MIN] > domains[-1, MAX]:
|
|
78
|
+
return PROP_INCONSISTENCY
|
|
79
|
+
return PROP_CONSISTENCY
|