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.
Files changed (150) hide show
  1. {nucs-2.3.0 → nucs-4.0.0/NUCS.egg-info}/PKG-INFO +1 -1
  2. {nucs-2.3.0 → nucs-4.0.0}/NUCS.egg-info/SOURCES.txt +30 -1
  3. {nucs-2.3.0/NUCS.egg-info → nucs-4.0.0}/PKG-INFO +1 -1
  4. {nucs-2.3.0 → nucs-4.0.0}/docs/source/conf.py +2 -2
  5. {nucs-2.3.0 → nucs-4.0.0}/nucs/constants.py +33 -7
  6. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/alpha/__main__.py +1 -1
  7. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/alpha/alpha_problem.py +1 -1
  8. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/bibd/__main__.py +1 -1
  9. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/donald/__main__.py +1 -1
  10. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/donald/donald_problem.py +1 -3
  11. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/golomb/golomb_problem.py +21 -9
  12. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/knapsack/__main__.py +1 -1
  13. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/magic_sequence/__main__.py +3 -2
  14. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/magic_sequence/magic_sequence_problem.py +1 -3
  15. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/magic_square/__main__.py +1 -1
  16. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/quasigroup/__main__.py +1 -1
  17. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/queens/__main__.py +22 -12
  18. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/sports_tournament_scheduling/__main__.py +1 -1
  19. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/sudoku/sudoku_problem.py +2 -16
  20. nucs-4.0.0/nucs/examples/tsp/__main__.py +43 -0
  21. nucs-4.0.0/nucs/examples/tsp/total_cost_propagator.py +79 -0
  22. nucs-4.0.0/nucs/examples/tsp/tsp_instances.py +72 -0
  23. nucs-4.0.0/nucs/examples/tsp/tsp_problem.py +50 -0
  24. nucs-4.0.0/nucs/heuristics/first_not_instantiated_var_heuristic.py +35 -0
  25. nucs-4.0.0/nucs/heuristics/greatest_domain_var_heuristic.py +40 -0
  26. nucs-4.0.0/nucs/heuristics/heuristics.py +58 -0
  27. nucs-4.0.0/nucs/heuristics/max_regret_var_heuristic.py +54 -0
  28. nucs-4.0.0/nucs/heuristics/max_value_dom_heuristic.py +58 -0
  29. nucs-4.0.0/nucs/heuristics/mid_value_dom_heuristic.py +47 -0
  30. nucs-4.0.0/nucs/heuristics/min_cost_dom_heuristic.py +52 -0
  31. nucs-4.0.0/nucs/heuristics/min_value_dom_heuristic.py +58 -0
  32. nucs-4.0.0/nucs/heuristics/smallest_domain_var_heuristic.py +42 -0
  33. nucs-4.0.0/nucs/heuristics/split_low_dom_heuristic.py +58 -0
  34. nucs-4.0.0/nucs/heuristics/value_dom_heuristic.py +78 -0
  35. {nucs-2.3.0 → nucs-4.0.0}/nucs/numpy_helper.py +2 -2
  36. nucs-4.0.0/nucs/problems/circuit_problem.py +33 -0
  37. {nucs-2.3.0 → nucs-4.0.0}/nucs/problems/problem.py +35 -26
  38. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/affine_eq_propagator.py +20 -31
  39. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/affine_geq_propagator.py +32 -17
  40. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/affine_leq_propagator.py +31 -16
  41. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/alldifferent_propagator.py +2 -2
  42. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/and_propagator.py +3 -3
  43. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/count_eq_propagator.py +2 -2
  44. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/dummy_propagator.py +2 -2
  45. nucs-4.0.0/nucs/propagators/element_iv_propagator.py +82 -0
  46. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/element_lic_propagator.py +17 -32
  47. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/element_liv_propagator.py +16 -17
  48. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/exactly_eq_propagator.py +2 -2
  49. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/exactly_true_propagator.py +2 -2
  50. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/gcc_propagator.py +2 -2
  51. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/lexicographic_leq_propagator.py +2 -2
  52. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/max_eq_propagator.py +2 -2
  53. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/max_leq_propagator.py +11 -5
  54. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/min_eq_propagator.py +2 -2
  55. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/min_geq_propagator.py +11 -5
  56. nucs-4.0.0/nucs/propagators/no_sub_cycle_propagator.py +78 -0
  57. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/propagators.py +20 -5
  58. {nucs-2.3.0 → nucs-4.0.0}/nucs/propagators/relation_propagator.py +2 -2
  59. nucs-4.0.0/nucs/propagators/scc_propagator.py +75 -0
  60. {nucs-2.3.0 → nucs-4.0.0}/nucs/solvers/backtrack_solver.py +99 -58
  61. {nucs-2.3.0 → nucs-4.0.0}/nucs/solvers/bound_consistency_algorithm.py +44 -35
  62. nucs-4.0.0/nucs/solvers/choice_points.py +75 -0
  63. {nucs-2.3.0 → nucs-4.0.0}/nucs/solvers/multiprocessing_solver.py +1 -4
  64. nucs-4.0.0/nucs/solvers/shaving_consistency_algorithm.py +213 -0
  65. {nucs-2.3.0 → nucs-4.0.0}/nucs/solvers/solver.py +44 -15
  66. {nucs-2.3.0 → nucs-4.0.0}/pyproject.toml +1 -1
  67. {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_alpha.py +1 -1
  68. {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_donald.py +1 -1
  69. {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_knapsack.py +1 -1
  70. {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_magic_sequence.py +5 -2
  71. {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_magic_square.py +1 -1
  72. {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_quasigroup.py +1 -1
  73. {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_queens.py +1 -1
  74. {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_sports_tournament_scheduling.py +1 -1
  75. nucs-4.0.0/tests/examples/test_tsp.py +47 -0
  76. nucs-4.0.0/tests/heuristics/test_max_value_dom_heuristic.py +24 -0
  77. nucs-4.0.0/tests/heuristics/test_mid_value_dom_heuristic.py +24 -0
  78. nucs-4.0.0/tests/heuristics/test_min_value_dom_heuristic.py +24 -0
  79. nucs-4.0.0/tests/problems/__init__.py +0 -0
  80. nucs-4.0.0/tests/problems/test_circuit_problem.py +36 -0
  81. nucs-4.0.0/tests/propagators/__init__.py +0 -0
  82. {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_affine_eq.py +1 -1
  83. {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_affine_geq.py +1 -1
  84. {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_affine_leq.py +1 -1
  85. nucs-4.0.0/tests/propagators/test_element_iv.py +36 -0
  86. {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_element_liv.py +5 -0
  87. nucs-4.0.0/tests/propagators/test_no_sub_cycle.py +27 -0
  88. nucs-4.0.0/tests/propagators/test_scc.py +32 -0
  89. nucs-4.0.0/tests/solvers/__init__.py +0 -0
  90. {nucs-2.3.0 → nucs-4.0.0}/tests/solvers/test_backtrack_solver.py +12 -2
  91. nucs-2.3.0/nucs/solvers/choice_points.py +0 -84
  92. nucs-2.3.0/nucs/solvers/heuristics.py +0 -165
  93. nucs-2.3.0/nucs/solvers/shaving_consistency_algorithm.py +0 -274
  94. {nucs-2.3.0 → nucs-4.0.0}/LICENSE.md +0 -0
  95. {nucs-2.3.0 → nucs-4.0.0}/NUCS.egg-info/dependency_links.txt +0 -0
  96. {nucs-2.3.0 → nucs-4.0.0}/NUCS.egg-info/requires.txt +0 -0
  97. {nucs-2.3.0 → nucs-4.0.0}/NUCS.egg-info/top_level.txt +0 -0
  98. {nucs-2.3.0 → nucs-4.0.0}/README.md +0 -0
  99. {nucs-2.3.0 → nucs-4.0.0}/nucs/__init__.py +0 -0
  100. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/__init__.py +0 -0
  101. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/alpha/__init__.py +0 -0
  102. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/bibd/__init__.py +0 -0
  103. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/bibd/bibd_problem.py +0 -0
  104. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/donald/__init__.py +0 -0
  105. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/golomb/__init__.py +0 -0
  106. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/golomb/__main__.py +0 -0
  107. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/knapsack/__init__.py +0 -0
  108. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/knapsack/knapsack_problem.py +0 -0
  109. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/magic_sequence/__init__.py +0 -0
  110. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/magic_square/__init__.py +0 -0
  111. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/magic_square/magic_square_problem.py +0 -0
  112. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/quasigroup/__init__.py +0 -0
  113. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/quasigroup/quasigroup_problem.py +0 -0
  114. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/queens/__init__.py +0 -0
  115. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/queens/queens_problem.py +0 -0
  116. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/schur_lemma/__init__.py +0 -0
  117. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/schur_lemma/__main__.py +0 -0
  118. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/schur_lemma/schur_lemma_problem.py +0 -0
  119. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/sports_tournament_scheduling/__init__.py +0 -0
  120. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/sports_tournament_scheduling/sports_tournament_scheduling_problem.py +0 -0
  121. {nucs-2.3.0 → nucs-4.0.0}/nucs/examples/sudoku/__init__.py +0 -0
  122. {nucs-2.3.0/nucs/problems → nucs-4.0.0/nucs/examples/tsp}/__init__.py +0 -0
  123. {nucs-2.3.0/nucs/propagators → nucs-4.0.0/nucs/heuristics}/__init__.py +0 -0
  124. {nucs-2.3.0 → nucs-4.0.0}/nucs/numba_helper.py +0 -0
  125. {nucs-2.3.0/nucs/solvers → nucs-4.0.0/nucs/problems}/__init__.py +0 -0
  126. {nucs-2.3.0 → nucs-4.0.0}/nucs/problems/latin_square_problem.py +0 -0
  127. {nucs-2.3.0/tests → nucs-4.0.0/nucs/propagators}/__init__.py +0 -0
  128. {nucs-2.3.0/tests/problems → nucs-4.0.0/nucs/solvers}/__init__.py +0 -0
  129. {nucs-2.3.0 → nucs-4.0.0}/nucs/solvers/consistency_algorithms.py +0 -0
  130. {nucs-2.3.0 → nucs-4.0.0}/setup.cfg +0 -0
  131. {nucs-2.3.0/tests/propagators → nucs-4.0.0/tests}/__init__.py +0 -0
  132. {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_bibd.py +0 -0
  133. {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_golomb.py +0 -0
  134. {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_latin_square.py +0 -0
  135. {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_schur_lemma.py +0 -0
  136. {nucs-2.3.0 → nucs-4.0.0}/tests/examples/test_sudokus.py +0 -0
  137. {nucs-2.3.0/tests/solvers → nucs-4.0.0/tests/heuristics}/__init__.py +0 -0
  138. {nucs-2.3.0 → nucs-4.0.0}/tests/problems/test_problem.py +0 -0
  139. {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_alldifferent.py +0 -0
  140. {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_count_eq.py +0 -0
  141. {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_element_lic.py +0 -0
  142. {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_exactly_eq.py +0 -0
  143. {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_gcc.py +0 -0
  144. {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_lexicographic_leq.py +0 -0
  145. {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_max_eq.py +0 -0
  146. {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_max_leq.py +0 -0
  147. {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_min_eq.py +0 -0
  148. {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_min_geq.py +0 -0
  149. {nucs-2.3.0 → nucs-4.0.0}/tests/propagators/test_relation.py +0 -0
  150. {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: 2.3.0
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: 2.3.0
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
@@ -6,8 +6,8 @@ project = 'NUCS'
6
6
  copyright = '2024, Yan Georget'
7
7
  author = 'Yan Georget'
8
8
 
9
- release = '2.3.0'
10
- version = '2.3.0'
9
+ release = '4.0.0'
10
+ version = '4.0.0'
11
11
 
12
12
  # -- General configuration
13
13
 
@@ -14,12 +14,24 @@ import os
14
14
 
15
15
  from numba import bool, int32, int64, types, uint8, uint16 # type: ignore
16
16
 
17
- START = 0 # index corresponding the start of a values range
18
- END = 1 # index corresponding the end of a values range
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
- bool[:, :, :], # shr_domains_propagators
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[:], # stacks_height
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 - %(levelname)s - %(name)s - %(message)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._typing import NDArray
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.variable_nb)), ALG_ALLDIFFERENT, []))
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
- stacks_height: NDArray,
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(shr_domains_stack[0]) # no domains shared between vars
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[0, dom_indices_arr[var_idx], MIN] # no offset
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[0, dom_idx, MIN] = minimal_sum[j - i] # no offset
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, not_entailed_propagators_stack[0], shr_domains_propagators, dom_idx, MIN
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
- stacks_height,
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
- var_heuristic_idx=VAR_HEURISTIC_LAST_NOT_INSTANTIATED,
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
- problems = problem.split(args.processors, 0)
36
- solver = MultiprocessingSolver(
37
- [
38
- BacktrackSolver(
39
- problem,
40
- consistency_alg_idx=CONSISTENCY_ALG_SHAVING if args.shaving else CONSISTENCY_ALG_BC,
41
- var_heuristic_idx=VAR_HEURISTIC_SMALLEST_DOMAIN if args.ff else VAR_HEURISTIC_FIRST_NOT_INSTANTIATED,
42
- log_level=args.log_level,
43
- )
44
- for problem in problems
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
- offset = i * 27 + j * 3
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