NUCS 4.2.0__tar.gz → 4.3.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.2.0 → nucs-4.3.0/NUCS.egg-info}/PKG-INFO +1 -1
- {nucs-4.2.0 → nucs-4.3.0}/NUCS.egg-info/SOURCES.txt +4 -2
- {nucs-4.2.0/NUCS.egg-info → nucs-4.3.0}/PKG-INFO +1 -1
- {nucs-4.2.0 → nucs-4.3.0}/docs/source/conf.py +2 -2
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/alpha/alpha_problem.py +3 -2
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/donald/donald_problem.py +4 -3
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/golomb/golomb_problem.py +2 -2
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/magic_square/__main__.py +1 -1
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/queens/queens_problem.py +2 -1
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/sports_tournament_scheduling/sports_tournament_scheduling_problem.py +1 -1
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/tsp/__main__.py +18 -13
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/tsp/total_cost_propagator.py +15 -4
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/tsp/tsp_problem.py +15 -9
- nucs-4.3.0/nucs/examples/tsp/tsp_var_heuristic.py +52 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/heuristics/greatest_domain_var_heuristic.py +7 -7
- {nucs-4.2.0 → nucs-4.3.0}/nucs/heuristics/max_regret_var_heuristic.py +18 -14
- {nucs-4.2.0 → nucs-4.3.0}/nucs/heuristics/smallest_domain_var_heuristic.py +7 -7
- {nucs-4.2.0 → nucs-4.3.0}/nucs/numba_helper.py +2 -2
- nucs-4.3.0/nucs/problems/circuit_problem.py +36 -0
- nucs-4.2.0/nucs/problems/circuit_problem.py → nucs-4.3.0/nucs/problems/permutation_problem.py +11 -10
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/gcc_propagator.py +9 -9
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/no_sub_cycle_propagator.py +21 -18
- nucs-4.3.0/nucs/propagators/permutation_aux_propagator.py +65 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/propagators.py +11 -4
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/scc_propagator.py +1 -1
- {nucs-4.2.0 → nucs-4.3.0}/nucs/solvers/backtrack_solver.py +4 -4
- {nucs-4.2.0 → nucs-4.3.0}/nucs/solvers/bound_consistency_algorithm.py +3 -3
- {nucs-4.2.0 → nucs-4.3.0}/nucs/solvers/choice_points.py +2 -2
- {nucs-4.2.0 → nucs-4.3.0}/nucs/solvers/multiprocessing_solver.py +2 -2
- {nucs-4.2.0 → nucs-4.3.0}/nucs/solvers/shaving_consistency_algorithm.py +2 -2
- {nucs-4.2.0 → nucs-4.3.0}/pyproject.toml +1 -1
- nucs-4.3.0/tests/examples/test_tsp.py +59 -0
- nucs-4.3.0/tests/problems/test_permutation_problem.py +35 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_no_sub_cycle.py +7 -2
- nucs-4.2.0/nucs/examples/tsp/mcp_dom_heuristic.py +0 -59
- nucs-4.2.0/nucs/examples/tsp/mrp_var_heuristic.py +0 -60
- nucs-4.2.0/tests/examples/test_tsp.py +0 -47
- {nucs-4.2.0 → nucs-4.3.0}/LICENSE.md +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/NUCS.egg-info/dependency_links.txt +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/NUCS.egg-info/requires.txt +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/NUCS.egg-info/top_level.txt +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/README.md +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/constants.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/alpha/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/alpha/__main__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/bibd/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/bibd/__main__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/bibd/bibd_problem.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/donald/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/donald/__main__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/golomb/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/golomb/__main__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/knapsack/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/knapsack/__main__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/knapsack/knapsack_problem.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/magic_sequence/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/magic_sequence/__main__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/magic_sequence/magic_sequence_problem.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/magic_square/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/magic_square/magic_square_problem.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/quasigroup/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/quasigroup/__main__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/quasigroup/quasigroup_problem.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/queens/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/queens/__main__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/schur_lemma/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/schur_lemma/__main__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/schur_lemma/schur_lemma_problem.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/sports_tournament_scheduling/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/sports_tournament_scheduling/__main__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/sudoku/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/sudoku/sudoku_problem.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/tsp/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/examples/tsp/tsp_instances.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/heuristics/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/heuristics/first_not_instantiated_var_heuristic.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/heuristics/heuristics.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/heuristics/max_value_dom_heuristic.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/heuristics/mid_value_dom_heuristic.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/heuristics/min_cost_dom_heuristic.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/heuristics/min_value_dom_heuristic.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/heuristics/split_high_dom_heuristic.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/heuristics/split_low_dom_heuristic.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/heuristics/value_dom_heuristic.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/numpy_helper.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/problems/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/problems/latin_square_problem.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/problems/problem.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/affine_eq_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/affine_geq_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/affine_leq_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/alldifferent_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/and_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/count_eq_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/dummy_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/element_iv_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/element_lic_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/element_liv_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/exactly_eq_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/exactly_true_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/lexicographic_leq_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/max_eq_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/max_leq_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/min_eq_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/min_geq_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/propagators/relation_propagator.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/solvers/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/solvers/consistency_algorithms.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/nucs/solvers/solver.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/setup.cfg +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/examples/test_alpha.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/examples/test_bibd.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/examples/test_donald.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/examples/test_golomb.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/examples/test_knapsack.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/examples/test_latin_square.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/examples/test_magic_sequence.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/examples/test_magic_square.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/examples/test_quasigroup.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/examples/test_queens.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/examples/test_schur_lemma.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/examples/test_sports_tournament_scheduling.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/examples/test_sudokus.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/heuristics/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/heuristics/test_max_value_dom_heuristic.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/heuristics/test_mid_value_dom_heuristic.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/heuristics/test_min_value_dom_heuristic.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/problems/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/problems/test_circuit_problem.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/problems/test_problem.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_affine_eq.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_affine_geq.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_affine_leq.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_alldifferent.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_count_eq.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_element_iv.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_element_lic.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_element_liv.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_exactly_eq.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_gcc.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_lexicographic_leq.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_max_eq.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_max_leq.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_min_eq.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_min_geq.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_relation.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/propagators/test_scc.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/solvers/__init__.py +0 -0
- {nucs-4.2.0 → nucs-4.3.0}/tests/solvers/test_backtrack_solver.py +0 -0
- {nucs-4.2.0 → nucs-4.3.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: 4.
|
|
3
|
+
Version: 4.3.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,11 +49,10 @@ 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
|
|
54
52
|
nucs/examples/tsp/total_cost_propagator.py
|
|
55
53
|
nucs/examples/tsp/tsp_instances.py
|
|
56
54
|
nucs/examples/tsp/tsp_problem.py
|
|
55
|
+
nucs/examples/tsp/tsp_var_heuristic.py
|
|
57
56
|
nucs/heuristics/__init__.py
|
|
58
57
|
nucs/heuristics/first_not_instantiated_var_heuristic.py
|
|
59
58
|
nucs/heuristics/greatest_domain_var_heuristic.py
|
|
@@ -70,6 +69,7 @@ nucs/heuristics/value_dom_heuristic.py
|
|
|
70
69
|
nucs/problems/__init__.py
|
|
71
70
|
nucs/problems/circuit_problem.py
|
|
72
71
|
nucs/problems/latin_square_problem.py
|
|
72
|
+
nucs/problems/permutation_problem.py
|
|
73
73
|
nucs/problems/problem.py
|
|
74
74
|
nucs/propagators/__init__.py
|
|
75
75
|
nucs/propagators/affine_eq_propagator.py
|
|
@@ -91,6 +91,7 @@ nucs/propagators/max_leq_propagator.py
|
|
|
91
91
|
nucs/propagators/min_eq_propagator.py
|
|
92
92
|
nucs/propagators/min_geq_propagator.py
|
|
93
93
|
nucs/propagators/no_sub_cycle_propagator.py
|
|
94
|
+
nucs/propagators/permutation_aux_propagator.py
|
|
94
95
|
nucs/propagators/propagators.py
|
|
95
96
|
nucs/propagators/relation_propagator.py
|
|
96
97
|
nucs/propagators/scc_propagator.py
|
|
@@ -123,6 +124,7 @@ tests/heuristics/test_mid_value_dom_heuristic.py
|
|
|
123
124
|
tests/heuristics/test_min_value_dom_heuristic.py
|
|
124
125
|
tests/problems/__init__.py
|
|
125
126
|
tests/problems/test_circuit_problem.py
|
|
127
|
+
tests/problems/test_permutation_problem.py
|
|
126
128
|
tests/problems/test_problem.py
|
|
127
129
|
tests/propagators/__init__.py
|
|
128
130
|
tests/propagators/test_affine_eq.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: NUCS
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.3.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
|
|
@@ -24,7 +24,7 @@ class AlphaProblem(Problem):
|
|
|
24
24
|
"""
|
|
25
25
|
The numbers from 1 to 26 are assigned to the letters of the alphabet.
|
|
26
26
|
The numbers beside each word are the total of the values assigned to the letters in the word
|
|
27
|
-
(
|
|
27
|
+
(eg for LYRE: L,Y,R,E might be to equal 5,9,20 and 13 or any other combination that add up to 47).
|
|
28
28
|
|
|
29
29
|
Find the value of each letter under the equations:
|
|
30
30
|
BALLET 45 GLEE 66 POLKA 59 SONG 61
|
|
@@ -67,7 +67,8 @@ class AlphaProblem(Problem):
|
|
|
67
67
|
]
|
|
68
68
|
)
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
@staticmethod
|
|
71
|
+
def solution_as_dict(solution: NDArray) -> Dict[str, int]:
|
|
71
72
|
"""
|
|
72
73
|
Returns the solution as a dict.
|
|
73
74
|
:param solution: the solution as a list of ints
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
#
|
|
11
11
|
# Copyright 2024 - Yan Georget
|
|
12
12
|
###############################################################################
|
|
13
|
-
from typing import Dict
|
|
13
|
+
from typing import Any, 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
|
|
@@ -40,7 +40,8 @@ class DonaldProblem(Problem):
|
|
|
40
40
|
)
|
|
41
41
|
self.add_propagator(([A, B, D, E, G, L, N, O, R, T], ALG_ALLDIFFERENT, []))
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
@staticmethod
|
|
44
|
+
def solution_as_dict(solution: NDArray) -> Dict[str, Any]:
|
|
44
45
|
"""
|
|
45
46
|
Returns the solution as a dict.
|
|
46
47
|
:param solution: the solution as a list of ints
|
|
@@ -19,7 +19,7 @@ from numpy.typing import NDArray
|
|
|
19
19
|
from nucs.constants import EVENT_MASK_GROUND, EVENT_MASK_MIN, MAX, MIN
|
|
20
20
|
from nucs.heuristics.heuristics import first_not_instantiated_var_heuristic
|
|
21
21
|
from nucs.problems.problem import Problem
|
|
22
|
-
from nucs.propagators.propagators import ALG_AFFINE_EQ, ALG_AFFINE_LEQ, ALG_ALLDIFFERENT,
|
|
22
|
+
from nucs.propagators.propagators import ALG_AFFINE_EQ, ALG_AFFINE_LEQ, ALG_ALLDIFFERENT, update_propagators
|
|
23
23
|
from nucs.solvers.bound_consistency_algorithm import bound_consistency_algorithm
|
|
24
24
|
|
|
25
25
|
GOLOMB_LENGTHS = np.array([0, 0, 1, 3, 6, 11, 17, 25, 34, 44, 55, 72, 85, 106, 127])
|
|
@@ -161,7 +161,7 @@ def golomb_consistency_algorithm(
|
|
|
161
161
|
events = EVENT_MASK_MIN
|
|
162
162
|
if shr_domains_stack[top, dom_idx, MIN] == shr_domains_stack[top, dom_idx, MAX]:
|
|
163
163
|
events |= EVENT_MASK_GROUND
|
|
164
|
-
|
|
164
|
+
update_propagators(
|
|
165
165
|
triggered_propagators,
|
|
166
166
|
not_entailed_propagators_stack[top],
|
|
167
167
|
shr_domains_propagators,
|
|
@@ -24,7 +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("-n", type=int)
|
|
27
|
+
parser.add_argument("-n", type=int, default=4)
|
|
28
28
|
parser.add_argument("--symmetry_breaking", action=argparse.BooleanOptionalAction, default=True)
|
|
29
29
|
args = parser.parse_args()
|
|
30
30
|
problem = MagicSquareProblem(args.n, args.symmetry_breaking)
|
|
@@ -37,6 +37,7 @@ class QueensProblem(Problem):
|
|
|
37
37
|
self.add_propagator((list(range(n, 2 * n)), ALG_ALLDIFFERENT, []))
|
|
38
38
|
self.add_propagator((list(range(2 * n, 3 * n)), ALG_ALLDIFFERENT, []))
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
@staticmethod
|
|
41
|
+
def solution_as_matrix(solution: List[int]) -> List[List[str]]:
|
|
41
42
|
n = len(solution)
|
|
42
43
|
return [([" "] * i + ["X"] + [" "] * (n - i - 1)) for i in range(n)]
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
###############################################################################
|
|
13
13
|
from typing import List
|
|
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_ALLDIFFERENT, ALG_EXACTLY_EQ, ALG_GCC, ALG_RELATION
|
|
@@ -15,7 +15,8 @@ import argparse
|
|
|
15
15
|
from nucs.constants import LOG_LEVEL_INFO, LOG_LEVELS, OPT_MODES, OPT_PRUNE
|
|
16
16
|
from nucs.examples.tsp.tsp_instances import TSP_INSTANCES
|
|
17
17
|
from nucs.examples.tsp.tsp_problem import TSPProblem
|
|
18
|
-
from nucs.
|
|
18
|
+
from nucs.examples.tsp.tsp_var_heuristic import tsp_var_heuristic
|
|
19
|
+
from nucs.heuristics.heuristics import DOM_HEURISTIC_MIN_COST, register_var_heuristic
|
|
19
20
|
from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
20
21
|
from nucs.solvers.consistency_algorithms import CONSISTENCY_ALG_BC, CONSISTENCY_ALG_SHAVING
|
|
21
22
|
from nucs.solvers.multiprocessing_solver import MultiprocessingSolver
|
|
@@ -28,21 +29,25 @@ if __name__ == "__main__":
|
|
|
28
29
|
parser.add_argument("--name", choices=["GR17", "GR21", "GR24"], default="GR17")
|
|
29
30
|
parser.add_argument("--opt_mode", choices=OPT_MODES, default=OPT_PRUNE)
|
|
30
31
|
parser.add_argument("--processors", type=int, default=1)
|
|
31
|
-
parser.add_argument("--shaving", type=bool, action=argparse.BooleanOptionalAction, default=
|
|
32
|
+
parser.add_argument("--shaving", type=bool, action=argparse.BooleanOptionalAction, default=False)
|
|
32
33
|
args = parser.parse_args()
|
|
33
34
|
tsp_instance = TSP_INSTANCES[args.name]
|
|
35
|
+
n = len(tsp_instance)
|
|
36
|
+
decision_domains = list(range(0, 2 * n))
|
|
34
37
|
problem = TSPProblem(tsp_instance)
|
|
38
|
+
costs = tsp_instance + tsp_instance # symmetry of costs
|
|
39
|
+
tsp_var_heuristic_idx = register_var_heuristic(tsp_var_heuristic)
|
|
35
40
|
solver = (
|
|
36
41
|
MultiprocessingSolver(
|
|
37
42
|
[
|
|
38
43
|
BacktrackSolver(
|
|
39
44
|
prob,
|
|
40
45
|
consistency_alg_idx=CONSISTENCY_ALG_SHAVING if args.shaving else CONSISTENCY_ALG_BC,
|
|
41
|
-
decision_domains=
|
|
42
|
-
var_heuristic_idx=
|
|
43
|
-
var_heuristic_params=
|
|
44
|
-
dom_heuristic_idx=DOM_HEURISTIC_MIN_COST,
|
|
45
|
-
dom_heuristic_params=
|
|
46
|
+
decision_domains=decision_domains,
|
|
47
|
+
var_heuristic_idx=tsp_var_heuristic_idx,
|
|
48
|
+
var_heuristic_params=costs,
|
|
49
|
+
dom_heuristic_idx=DOM_HEURISTIC_MIN_COST,
|
|
50
|
+
dom_heuristic_params=costs,
|
|
46
51
|
log_level=args.log_level,
|
|
47
52
|
)
|
|
48
53
|
for prob in problem.split(args.processors, 0)
|
|
@@ -52,13 +57,13 @@ if __name__ == "__main__":
|
|
|
52
57
|
else BacktrackSolver(
|
|
53
58
|
problem,
|
|
54
59
|
consistency_alg_idx=CONSISTENCY_ALG_SHAVING if args.shaving else CONSISTENCY_ALG_BC,
|
|
55
|
-
decision_domains=
|
|
56
|
-
var_heuristic_idx=
|
|
57
|
-
var_heuristic_params=
|
|
58
|
-
dom_heuristic_idx=DOM_HEURISTIC_MIN_COST,
|
|
59
|
-
dom_heuristic_params=
|
|
60
|
+
decision_domains=decision_domains,
|
|
61
|
+
var_heuristic_idx=tsp_var_heuristic_idx,
|
|
62
|
+
var_heuristic_params=costs,
|
|
63
|
+
dom_heuristic_idx=DOM_HEURISTIC_MIN_COST,
|
|
64
|
+
dom_heuristic_params=costs,
|
|
60
65
|
log_level=args.log_level,
|
|
61
66
|
)
|
|
62
67
|
)
|
|
63
|
-
solution = solver.minimize(problem.
|
|
68
|
+
solution = solver.minimize(problem.total_cost, mode=args.opt_mode)
|
|
64
69
|
print(solver.get_statistics())
|
|
@@ -26,7 +26,7 @@ def get_complexity_total_cost(n: int, parameters: NDArray) -> float:
|
|
|
26
26
|
:param parameters: the parameters, unused here
|
|
27
27
|
:return: a float
|
|
28
28
|
"""
|
|
29
|
-
return
|
|
29
|
+
return n * n
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def get_triggers_total_cost(n: int, parameters: NDArray) -> NDArray:
|
|
@@ -53,7 +53,18 @@ def compute_domains_total_cost(domains: NDArray, parameters: NDArray) -> int:
|
|
|
53
53
|
for i in range(n):
|
|
54
54
|
if domains[i, MIN] == domains[i, MAX]:
|
|
55
55
|
used[domains[i, MIN]] = True
|
|
56
|
-
global_min =
|
|
56
|
+
global_min = 0
|
|
57
|
+
# for j in range(n):
|
|
58
|
+
# max_regret = 0
|
|
59
|
+
# min_cost = min([costs[i, j] for i in range(n) if costs[i,j] > 0])
|
|
60
|
+
# for i in range(n):
|
|
61
|
+
# if costs[i, j] == min_cost:
|
|
62
|
+
# regret = compute_regret(domains[i], costs[i])
|
|
63
|
+
# if regret > max_regret:
|
|
64
|
+
# max_regret = regret
|
|
65
|
+
# global_min += regret
|
|
66
|
+
# global_min -= max_regret
|
|
67
|
+
global_max = 0
|
|
57
68
|
for i in range(n):
|
|
58
69
|
if domains[i, MIN] == domains[i, MAX]:
|
|
59
70
|
local_min = local_max = parameters[i * n + domains[i, MIN]]
|
|
@@ -68,8 +79,8 @@ def compute_domains_total_cost(domains: NDArray, parameters: NDArray) -> int:
|
|
|
68
79
|
local_min = cost
|
|
69
80
|
if cost > local_max:
|
|
70
81
|
local_max = cost
|
|
71
|
-
if local_min > local_max:
|
|
72
|
-
|
|
82
|
+
# if local_min > local_max:
|
|
83
|
+
# return PROP_INCONSISTENCY
|
|
73
84
|
global_min += local_min
|
|
74
85
|
global_max += local_max
|
|
75
86
|
domains[-1, MIN] = max(domains[-1, MIN], global_min)
|
|
@@ -33,15 +33,21 @@ class TSPProblem(CircuitProblem):
|
|
|
33
33
|
super().__init__(n)
|
|
34
34
|
max_costs = [max(cost_row) for cost_row in cost_rows]
|
|
35
35
|
min_costs = [min([cost for cost in cost_row if cost > 0]) for cost_row in cost_rows]
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
self.next_costs = self.add_variables([(min_costs[i], max_costs[i]) for i in range(n)])
|
|
37
|
+
self.prev_costs = self.add_variables([(min_costs[i], max_costs[i]) for i in range(n)])
|
|
38
|
+
self.total_cost = self.add_variable((sum(min_costs), sum(max_costs))) # the total cost
|
|
38
39
|
for i in range(n):
|
|
39
|
-
self.add_propagator(([i,
|
|
40
|
-
|
|
40
|
+
self.add_propagator(([i, self.next_costs + i], ALG_ELEMENT_IV, cost_rows[i]))
|
|
41
|
+
self.add_propagator(([n + i, self.prev_costs + i], ALG_ELEMENT_IV, cost_rows[i]))
|
|
41
42
|
self.add_propagator(
|
|
42
|
-
(
|
|
43
|
-
list(range(0, n)) + [total_cost_var],
|
|
44
|
-
register_propagator(get_triggers_total_cost, get_complexity_total_cost, compute_domains_total_cost),
|
|
45
|
-
[cost for cost_row in cost_rows for cost in cost_row],
|
|
46
|
-
)
|
|
43
|
+
(list(range(self.next_costs, self.next_costs + n)) + [self.total_cost], ALG_AFFINE_EQ, [1] * n + [-1, 0])
|
|
47
44
|
)
|
|
45
|
+
self.add_propagator(
|
|
46
|
+
(list(range(self.prev_costs, self.prev_costs + n)) + [self.total_cost], ALG_AFFINE_EQ, [1] * n + [-1, 0])
|
|
47
|
+
)
|
|
48
|
+
total_cost_prop_idx = register_propagator(
|
|
49
|
+
get_triggers_total_cost, get_complexity_total_cost, compute_domains_total_cost
|
|
50
|
+
)
|
|
51
|
+
costs = [cost for cost_row in cost_rows for cost in cost_row]
|
|
52
|
+
self.add_propagator((list(range(n)) + [self.total_cost], total_cost_prop_idx, costs))
|
|
53
|
+
self.add_propagator((list(range(n, 2 * n)) + [self.total_cost], total_cost_prop_idx, costs))
|
|
@@ -0,0 +1,52 @@
|
|
|
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
|
+
from numba import njit # type: ignore
|
|
16
|
+
from numpy.typing import NDArray
|
|
17
|
+
|
|
18
|
+
from nucs.constants import MAX, MIN
|
|
19
|
+
from nucs.heuristics.max_regret_var_heuristic import regret
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@njit(cache=True)
|
|
23
|
+
def tsp_var_heuristic(
|
|
24
|
+
decision_domains: NDArray, shr_domains_stack: NDArray, stacks_top: NDArray, params: NDArray
|
|
25
|
+
) -> int:
|
|
26
|
+
"""
|
|
27
|
+
:param decision_domains: the indices of a subset of the shared domains
|
|
28
|
+
:param shr_domains_stack: the stack of shared domains
|
|
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
|
+
:return: the index of the shared domain
|
|
32
|
+
"""
|
|
33
|
+
best_score = -sys.maxsize
|
|
34
|
+
best_idx = -1
|
|
35
|
+
top = stacks_top[0]
|
|
36
|
+
for dom_idx in decision_domains:
|
|
37
|
+
shr_domain = shr_domains_stack[top, dom_idx]
|
|
38
|
+
if 0 < shr_domain[MAX] - shr_domain[MIN]:
|
|
39
|
+
score = compute_score(shr_domain, dom_idx, params)
|
|
40
|
+
if best_score < score:
|
|
41
|
+
best_idx = dom_idx
|
|
42
|
+
best_score = score
|
|
43
|
+
return best_idx
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@njit(cache=True)
|
|
47
|
+
def compute_score(shr_domain: NDArray, dom_idx: int, params: NDArray) -> int:
|
|
48
|
+
"""
|
|
49
|
+
Minimize [min(5, size(X)), -regret(X)] for lexicographic order.
|
|
50
|
+
"""
|
|
51
|
+
size = min(12, shr_domain[MAX] - shr_domain[MIN] + 1)
|
|
52
|
+
return -size * 1024 + regret(shr_domain, params[dom_idx])
|
|
@@ -28,13 +28,13 @@ def greatest_domain_var_heuristic(
|
|
|
28
28
|
:param params: a two-dimensional parameters array, unused here
|
|
29
29
|
:return: the index of the shared domain
|
|
30
30
|
"""
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
best_score = 0
|
|
32
|
+
best_idx = -1
|
|
33
33
|
top = stacks_top[0]
|
|
34
34
|
for dom_idx in decision_domains:
|
|
35
35
|
shr_domain = shr_domains_stack[top, dom_idx]
|
|
36
|
-
|
|
37
|
-
if
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return
|
|
36
|
+
score = shr_domain[MAX] - shr_domain[MIN] # this is size - 1
|
|
37
|
+
if best_score < score:
|
|
38
|
+
best_idx = dom_idx
|
|
39
|
+
best_score = score
|
|
40
|
+
return best_idx
|
|
@@ -30,24 +30,28 @@ def max_regret_var_heuristic(
|
|
|
30
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
|
+
best_score = 0
|
|
34
34
|
best_idx = -1
|
|
35
35
|
top = stacks_top[0]
|
|
36
36
|
for dom_idx in decision_domains:
|
|
37
37
|
shr_domain = shr_domains_stack[top, dom_idx]
|
|
38
38
|
if 0 < shr_domain[MAX] - shr_domain[MIN]:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
for value in range(shr_domain[MIN], shr_domain[MAX] + 1):
|
|
42
|
-
cost = params[dom_idx][value]
|
|
43
|
-
if cost > 0:
|
|
44
|
-
if cost < best_cost:
|
|
45
|
-
second_cost = best_cost
|
|
46
|
-
best_cost = cost
|
|
47
|
-
elif cost < second_cost:
|
|
48
|
-
second_cost = cost
|
|
49
|
-
regret = second_cost - best_cost
|
|
50
|
-
if max_regret < regret:
|
|
39
|
+
score = regret(shr_domain, params[dom_idx])
|
|
40
|
+
if best_score < score:
|
|
51
41
|
best_idx = dom_idx
|
|
52
|
-
|
|
42
|
+
best_score = score
|
|
53
43
|
return best_idx
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@njit(cache=True)
|
|
47
|
+
def regret(domain: NDArray, costs: NDArray) -> int:
|
|
48
|
+
best_cost = sys.maxsize
|
|
49
|
+
second_cost = sys.maxsize
|
|
50
|
+
for value in range(domain[MIN], domain[MAX] + 1):
|
|
51
|
+
cost = costs[value]
|
|
52
|
+
if 0 < cost < best_cost:
|
|
53
|
+
second_cost = best_cost
|
|
54
|
+
best_cost = cost
|
|
55
|
+
elif 0 < cost < second_cost:
|
|
56
|
+
second_cost = cost
|
|
57
|
+
return second_cost - best_cost
|
|
@@ -30,13 +30,13 @@ def smallest_domain_var_heuristic(
|
|
|
30
30
|
:param params: a two-dimensional parameters array, unused here
|
|
31
31
|
:return: the index of the shared domain
|
|
32
32
|
"""
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
best_score = -sys.maxsize
|
|
34
|
+
best_idx = -1
|
|
35
35
|
top = stacks_top[0]
|
|
36
36
|
for dom_idx in decision_domains:
|
|
37
37
|
shr_domain = shr_domains_stack[top, dom_idx]
|
|
38
|
-
|
|
39
|
-
if
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return
|
|
38
|
+
score = shr_domain[MIN] - shr_domain[MAX]
|
|
39
|
+
if best_score < score < 0:
|
|
40
|
+
best_idx = dom_idx
|
|
41
|
+
best_score = score
|
|
42
|
+
return best_idx
|
|
@@ -26,9 +26,9 @@ def function_from_address(typingctx, func_type_ref: types.FunctionType, addr: in
|
|
|
26
26
|
func_type = func_type_ref.instance_type
|
|
27
27
|
|
|
28
28
|
def codegen(context, builder, sig, args): # type: ignore
|
|
29
|
-
_,
|
|
29
|
+
_, address = args
|
|
30
30
|
sfunc = cgutils.create_struct_proxy(func_type)(context, builder)
|
|
31
|
-
sfunc.addr = builder.inttoptr(
|
|
31
|
+
sfunc.addr = builder.inttoptr(address, context.get_value_type(types.voidptr))
|
|
32
32
|
return sfunc._getvalue()
|
|
33
33
|
|
|
34
34
|
return func_type(func_type_ref, addr), codegen
|
|
@@ -0,0 +1,36 @@
|
|
|
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
|
+
from nucs.problems.permutation_problem import PermutationProblem
|
|
14
|
+
from nucs.propagators.propagators import ALG_NO_SUB_CYCLE
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class CircuitProblem(PermutationProblem):
|
|
18
|
+
"""
|
|
19
|
+
A model for circuit.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, n: int):
|
|
23
|
+
"""
|
|
24
|
+
Inits the circuit problem.
|
|
25
|
+
:param n: the number of vertices
|
|
26
|
+
"""
|
|
27
|
+
self.n = n
|
|
28
|
+
super().__init__(n)
|
|
29
|
+
self.shr_domains_lst[0] = [1, n - 1]
|
|
30
|
+
self.shr_domains_lst[n - 1] = [0, n - 2]
|
|
31
|
+
self.shr_domains_lst[n] = [1, n - 1]
|
|
32
|
+
self.shr_domains_lst[2 * n - 1] = [0, n - 2]
|
|
33
|
+
self.add_propagator((list(range(n)), ALG_NO_SUB_CYCLE, []))
|
|
34
|
+
self.add_propagator((list(range(n, 2 * n)), ALG_NO_SUB_CYCLE, []))
|
|
35
|
+
# self.add_propagator((list(range(n)), ALG_SCC, [])) # not worth the cost
|
|
36
|
+
# self.add_propagator((list(range(n, 2*n)), ALG_SCC, [])) # not worth the cost
|
nucs-4.2.0/nucs/problems/circuit_problem.py → nucs-4.3.0/nucs/problems/permutation_problem.py
RENAMED
|
@@ -11,23 +11,24 @@
|
|
|
11
11
|
# Copyright 2024 - Yan Georget
|
|
12
12
|
###############################################################################
|
|
13
13
|
from nucs.problems.problem import Problem
|
|
14
|
-
from nucs.propagators.propagators import ALG_ALLDIFFERENT,
|
|
14
|
+
from nucs.propagators.propagators import ALG_ALLDIFFERENT, ALG_PERMUTATION_AUX
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
class
|
|
17
|
+
class PermutationProblem(Problem):
|
|
18
18
|
"""
|
|
19
|
-
A model for
|
|
19
|
+
A model for permutation.
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
22
|
def __init__(self, n: int):
|
|
23
23
|
"""
|
|
24
|
-
Inits the
|
|
25
|
-
:param n: the number
|
|
24
|
+
Inits the permutation problem.
|
|
25
|
+
:param n: the number variables/values
|
|
26
26
|
"""
|
|
27
27
|
self.n = n
|
|
28
|
-
shr_domains = [(
|
|
28
|
+
shr_domains = [(0, n - 1)] * 2 * n
|
|
29
29
|
super().__init__(shr_domains)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
for i in range(n):
|
|
31
|
+
self.add_propagator((list(range(n)) + [n + i], ALG_PERMUTATION_AUX, [i]))
|
|
32
|
+
self.add_propagator((list(range(n, 2 * n)) + [i], ALG_PERMUTATION_AUX, [i]))
|
|
33
|
+
self.add_propagator((list(range(n)), ALG_ALLDIFFERENT, []))
|
|
34
|
+
self.add_propagator((list(range(n, 2 * n)), ALG_ALLDIFFERENT, []))
|
|
@@ -44,7 +44,7 @@ def init_partial_sum(first_value: int, m: int, values: NDArray) -> NDArray:
|
|
|
44
44
|
"""
|
|
45
45
|
Inits the partial_sum data structure:
|
|
46
46
|
---------------------
|
|
47
|
-
|
|
|
47
|
+
| sm | first_value |
|
|
48
48
|
---------------------
|
|
49
49
|
| ds | last_value |
|
|
50
50
|
---------------------
|
|
@@ -52,19 +52,19 @@ def init_partial_sum(first_value: int, m: int, values: NDArray) -> NDArray:
|
|
|
52
52
|
partial_sum = np.zeros((2, m + 6), dtype=np.int32)
|
|
53
53
|
partial_sum[0, -1] = first_value - 3
|
|
54
54
|
partial_sum[1, -1] = first_value + m + 1
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
sm = partial_sum[0, :-1]
|
|
56
|
+
sm[0] = 0
|
|
57
|
+
sm[1] = 1
|
|
58
|
+
sm[2] = 2
|
|
59
59
|
for i in range(2, m + 2):
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
sm[i + 1] = sm[i] + values[i - 2]
|
|
61
|
+
sm[m + 3] = sm[m + 2] + 1
|
|
62
|
+
sm[m + 4] = sm[m + 3] + 1
|
|
63
63
|
ds = partial_sum[1, :-1]
|
|
64
64
|
i = m + 3
|
|
65
65
|
j = m + 4
|
|
66
66
|
while i > 0:
|
|
67
|
-
while
|
|
67
|
+
while sm[i] == sm[i - 1]:
|
|
68
68
|
ds[i] = j
|
|
69
69
|
i -= 1
|
|
70
70
|
ds[j] = i
|
|
@@ -56,23 +56,26 @@ def compute_domains_no_sub_cycle(domains: NDArray, parameters: NDArray) -> int:
|
|
|
56
56
|
while loop:
|
|
57
57
|
loop = False
|
|
58
58
|
for i in range(n):
|
|
59
|
-
if domains[i, MIN] == domains[i, MAX]
|
|
59
|
+
if domains[i, MIN] == domains[i, MAX]:
|
|
60
60
|
j = domains[i, MIN]
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
paths[
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if
|
|
73
|
-
domains[end,
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
61
|
+
if i == j:
|
|
62
|
+
return PROP_INCONSISTENCY
|
|
63
|
+
if paths[i, PATH_END] == i:
|
|
64
|
+
end = paths[i, PATH_END] = paths[j, PATH_END]
|
|
65
|
+
start = paths[j, PATH_START] = paths[i, PATH_START]
|
|
66
|
+
paths[start, PATH_END] = end
|
|
67
|
+
paths[end, PATH_START] = start
|
|
68
|
+
length = paths[i, PATH_LENGTH] + 1 + paths[j, PATH_LENGTH]
|
|
69
|
+
paths[i, PATH_LENGTH] = paths[j, PATH_LENGTH] = paths[start, PATH_LENGTH] = paths[
|
|
70
|
+
end, PATH_LENGTH
|
|
71
|
+
] = length
|
|
72
|
+
if length < n - 1:
|
|
73
|
+
if domains[end, MIN] == start:
|
|
74
|
+
domains[end, MIN] = start + 1
|
|
75
|
+
if domains[end, MAX] == start:
|
|
76
|
+
domains[end, MAX] = start - 1
|
|
77
|
+
if domains[end, MIN] > domains[end, MAX]:
|
|
78
|
+
return PROP_INCONSISTENCY
|
|
79
|
+
if end < i:
|
|
80
|
+
loop = True
|
|
78
81
|
return PROP_CONSISTENCY
|