NUCS 7.0.0__tar.gz → 7.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. {nucs-7.0.0 → nucs-7.2.0/NuCS.egg-info}/PKG-INFO +1 -1
  2. {nucs-7.0.0 → nucs-7.2.0}/NuCS.egg-info/SOURCES.txt +7 -0
  3. {nucs-7.0.0/NuCS.egg-info → nucs-7.2.0}/PKG-INFO +1 -1
  4. {nucs-7.0.0 → nucs-7.2.0}/docs/source/conf.py +2 -2
  5. nucs-7.2.0/nucs/examples/employee_scheduling/__main__.py +31 -0
  6. nucs-7.2.0/nucs/examples/employee_scheduling/employee_scheduling_problem.py +107 -0
  7. {nucs-7.0.0 → nucs-7.2.0}/nucs/problems/problem.py +2 -2
  8. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/affine_eq_propagator.py +1 -1
  9. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/affine_geq_propagator.py +1 -1
  10. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/affine_leq_propagator.py +1 -1
  11. nucs-7.2.0/nucs/propagators/count_geq_c_propagator.py +65 -0
  12. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/count_leq_c_propagator.py +2 -2
  13. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/propagators.py +6 -0
  14. {nucs-7.0.0 → nucs-7.2.0}/pyproject.toml +1 -1
  15. nucs-7.2.0/tests/examples/test_employee_scheduling.py +27 -0
  16. nucs-7.2.0/tests/propagators/__init__.py +0 -0
  17. nucs-7.2.0/tests/propagators/test_count_geq_c.py +55 -0
  18. nucs-7.2.0/tests/solvers/__init__.py +0 -0
  19. {nucs-7.0.0 → nucs-7.2.0}/LICENSE.md +0 -0
  20. {nucs-7.0.0 → nucs-7.2.0}/NuCS.egg-info/dependency_links.txt +0 -0
  21. {nucs-7.0.0 → nucs-7.2.0}/NuCS.egg-info/requires.txt +0 -0
  22. {nucs-7.0.0 → nucs-7.2.0}/NuCS.egg-info/top_level.txt +0 -0
  23. {nucs-7.0.0 → nucs-7.2.0}/README.md +0 -0
  24. {nucs-7.0.0 → nucs-7.2.0}/docs/source/queens.py +0 -0
  25. {nucs-7.0.0 → nucs-7.2.0}/nucs/__init__.py +0 -0
  26. {nucs-7.0.0 → nucs-7.2.0}/nucs/constants.py +0 -0
  27. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/__init__.py +0 -0
  28. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/all_interval_series/__init__.py +0 -0
  29. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/all_interval_series/__main__.py +0 -0
  30. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/all_interval_series/all_interval_series_problem.py +0 -0
  31. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/alpha/__init__.py +0 -0
  32. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/alpha/__main__.py +0 -0
  33. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/alpha/alpha_problem.py +0 -0
  34. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/bibd/__init__.py +0 -0
  35. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/bibd/__main__.py +0 -0
  36. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/bibd/bibd_problem.py +0 -0
  37. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/default_argument_parser.py +0 -0
  38. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/donald/__init__.py +0 -0
  39. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/donald/__main__.py +0 -0
  40. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/donald/donald_problem.py +0 -0
  41. {nucs-7.0.0/nucs/examples/golomb → nucs-7.2.0/nucs/examples/employee_scheduling}/__init__.py +0 -0
  42. {nucs-7.0.0/nucs/examples/knapsack → nucs-7.2.0/nucs/examples/golomb}/__init__.py +0 -0
  43. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/golomb/__main__.py +0 -0
  44. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/golomb/golomb_problem.py +0 -0
  45. {nucs-7.0.0/nucs/examples/latin_square → nucs-7.2.0/nucs/examples/knapsack}/__init__.py +0 -0
  46. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/knapsack/__main__.py +0 -0
  47. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/knapsack/knapsack_problem.py +0 -0
  48. {nucs-7.0.0/nucs/examples/magic_sequence → nucs-7.2.0/nucs/examples/latin_square}/__init__.py +0 -0
  49. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/latin_square/__main__.py +0 -0
  50. {nucs-7.0.0/nucs/examples/magic_square → nucs-7.2.0/nucs/examples/magic_sequence}/__init__.py +0 -0
  51. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/magic_sequence/__main__.py +0 -0
  52. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/magic_sequence/magic_sequence_problem.py +0 -0
  53. {nucs-7.0.0/nucs/examples/quasigroup → nucs-7.2.0/nucs/examples/magic_square}/__init__.py +0 -0
  54. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/magic_square/__main__.py +0 -0
  55. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/magic_square/magic_square_problem.py +0 -0
  56. {nucs-7.0.0/nucs/examples/queens → nucs-7.2.0/nucs/examples/quasigroup}/__init__.py +0 -0
  57. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/quasigroup/__main__.py +0 -0
  58. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/quasigroup/quasigroup_problem.py +0 -0
  59. {nucs-7.0.0/nucs/examples/schur_lemma → nucs-7.2.0/nucs/examples/queens}/__init__.py +0 -0
  60. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/queens/__main__.py +0 -0
  61. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/queens/queens_problem.py +0 -0
  62. {nucs-7.0.0/nucs/examples/sports_tournament_scheduling → nucs-7.2.0/nucs/examples/schur_lemma}/__init__.py +0 -0
  63. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/schur_lemma/__main__.py +0 -0
  64. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/schur_lemma/schur_lemma_problem.py +0 -0
  65. {nucs-7.0.0/nucs/examples/sudoku → nucs-7.2.0/nucs/examples/sports_tournament_scheduling}/__init__.py +0 -0
  66. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/sports_tournament_scheduling/__main__.py +0 -0
  67. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/sports_tournament_scheduling/sports_tournament_scheduling_problem.py +0 -0
  68. {nucs-7.0.0/nucs/examples/tsp → nucs-7.2.0/nucs/examples/sudoku}/__init__.py +0 -0
  69. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/sudoku/sudoku_problem.py +0 -0
  70. {nucs-7.0.0/nucs/heuristics → nucs-7.2.0/nucs/examples/tsp}/__init__.py +0 -0
  71. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/tsp/__main__.py +0 -0
  72. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/tsp/total_cost_propagator.py +0 -0
  73. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/tsp/tsp_instances.py +0 -0
  74. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/tsp/tsp_problem.py +0 -0
  75. {nucs-7.0.0 → nucs-7.2.0}/nucs/examples/tsp/tsp_var_heuristic.py +0 -0
  76. {nucs-7.0.0 → nucs-7.2.0}/nucs/heaps.py +0 -0
  77. {nucs-7.0.0/nucs/problems → nucs-7.2.0/nucs/heuristics}/__init__.py +0 -0
  78. {nucs-7.0.0 → nucs-7.2.0}/nucs/heuristics/first_not_instantiated_var_heuristic.py +0 -0
  79. {nucs-7.0.0 → nucs-7.2.0}/nucs/heuristics/greatest_domain_var_heuristic.py +0 -0
  80. {nucs-7.0.0 → nucs-7.2.0}/nucs/heuristics/heuristics.py +0 -0
  81. {nucs-7.0.0 → nucs-7.2.0}/nucs/heuristics/max_regret_var_heuristic.py +0 -0
  82. {nucs-7.0.0 → nucs-7.2.0}/nucs/heuristics/max_value_dom_heuristic.py +0 -0
  83. {nucs-7.0.0 → nucs-7.2.0}/nucs/heuristics/mid_value_dom_heuristic.py +0 -0
  84. {nucs-7.0.0 → nucs-7.2.0}/nucs/heuristics/min_cost_dom_heuristic.py +0 -0
  85. {nucs-7.0.0 → nucs-7.2.0}/nucs/heuristics/min_value_dom_heuristic.py +0 -0
  86. {nucs-7.0.0 → nucs-7.2.0}/nucs/heuristics/smallest_domain_var_heuristic.py +0 -0
  87. {nucs-7.0.0 → nucs-7.2.0}/nucs/heuristics/split_high_dom_heuristic.py +0 -0
  88. {nucs-7.0.0 → nucs-7.2.0}/nucs/heuristics/split_low_dom_heuristic.py +0 -0
  89. {nucs-7.0.0 → nucs-7.2.0}/nucs/heuristics/split_random_dom_heuristic.py +0 -0
  90. {nucs-7.0.0 → nucs-7.2.0}/nucs/heuristics/value_dom_heuristic.py +0 -0
  91. {nucs-7.0.0 → nucs-7.2.0}/nucs/numba_helper.py +0 -0
  92. {nucs-7.0.0/nucs/propagators → nucs-7.2.0/nucs/problems}/__init__.py +0 -0
  93. {nucs-7.0.0 → nucs-7.2.0}/nucs/problems/circuit_problem.py +0 -0
  94. {nucs-7.0.0 → nucs-7.2.0}/nucs/problems/latin_square_problem.py +0 -0
  95. {nucs-7.0.0 → nucs-7.2.0}/nucs/problems/permutation_problem.py +0 -0
  96. {nucs-7.0.0/nucs/solvers → nucs-7.2.0/nucs/propagators}/__init__.py +0 -0
  97. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/abs_eq_propagator.py +0 -0
  98. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/alldifferent_propagator.py +0 -0
  99. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/and_eq_propagator.py +0 -0
  100. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/count_eq_c_propagator.py +0 -0
  101. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/count_eq_propagator.py +0 -0
  102. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/dummy_propagator.py +0 -0
  103. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/element_eq_propagator.py +0 -0
  104. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/element_l_eq_alldifferent_propagator.py +0 -0
  105. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/element_l_eq_c_alldifferent_propagator.py +0 -0
  106. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/element_l_eq_c_propagator.py +0 -0
  107. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/element_l_eq_propagator.py +0 -0
  108. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/equiv_eq_propagator.py +0 -0
  109. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/gcc_propagator.py +0 -0
  110. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/lexicographic_leq_propagator.py +0 -0
  111. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/max_eq_propagator.py +0 -0
  112. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/max_leq_propagator.py +0 -0
  113. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/min_eq_propagator.py +0 -0
  114. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/min_geq_propagator.py +0 -0
  115. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/no_sub_cycle_propagator.py +0 -0
  116. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/permutation_aux_propagator.py +0 -0
  117. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/relation_propagator.py +0 -0
  118. {nucs-7.0.0 → nucs-7.2.0}/nucs/propagators/scc_propagator.py +0 -0
  119. {nucs-7.0.0/tests → nucs-7.2.0/nucs/solvers}/__init__.py +0 -0
  120. {nucs-7.0.0 → nucs-7.2.0}/nucs/solvers/backtrack_solver.py +0 -0
  121. {nucs-7.0.0 → nucs-7.2.0}/nucs/solvers/bound_consistency_algorithm.py +0 -0
  122. {nucs-7.0.0 → nucs-7.2.0}/nucs/solvers/choice_points.py +0 -0
  123. {nucs-7.0.0 → nucs-7.2.0}/nucs/solvers/consistency_algorithms.py +0 -0
  124. {nucs-7.0.0 → nucs-7.2.0}/nucs/solvers/multiprocessing_solver.py +0 -0
  125. {nucs-7.0.0 → nucs-7.2.0}/nucs/solvers/queue_solver.py +0 -0
  126. {nucs-7.0.0 → nucs-7.2.0}/nucs/solvers/shaving_consistency_algorithm.py +0 -0
  127. {nucs-7.0.0 → nucs-7.2.0}/nucs/solvers/solver.py +0 -0
  128. {nucs-7.0.0 → nucs-7.2.0}/setup.cfg +0 -0
  129. {nucs-7.0.0/tests/heuristics → nucs-7.2.0/tests}/__init__.py +0 -0
  130. {nucs-7.0.0/tests/problems → nucs-7.2.0/tests/examples}/__init__.py +0 -0
  131. {nucs-7.0.0 → nucs-7.2.0}/tests/examples/test_all_interval_series.py +0 -0
  132. {nucs-7.0.0 → nucs-7.2.0}/tests/examples/test_alpha.py +0 -0
  133. {nucs-7.0.0 → nucs-7.2.0}/tests/examples/test_bibd.py +0 -0
  134. {nucs-7.0.0 → nucs-7.2.0}/tests/examples/test_donald.py +0 -0
  135. {nucs-7.0.0 → nucs-7.2.0}/tests/examples/test_golomb.py +0 -0
  136. {nucs-7.0.0 → nucs-7.2.0}/tests/examples/test_knapsack.py +0 -0
  137. {nucs-7.0.0 → nucs-7.2.0}/tests/examples/test_latin_square.py +0 -0
  138. {nucs-7.0.0 → nucs-7.2.0}/tests/examples/test_magic_sequence.py +0 -0
  139. {nucs-7.0.0 → nucs-7.2.0}/tests/examples/test_magic_square.py +0 -0
  140. {nucs-7.0.0 → nucs-7.2.0}/tests/examples/test_quasigroup.py +0 -0
  141. {nucs-7.0.0 → nucs-7.2.0}/tests/examples/test_queens.py +0 -0
  142. {nucs-7.0.0 → nucs-7.2.0}/tests/examples/test_schur_lemma.py +0 -0
  143. {nucs-7.0.0 → nucs-7.2.0}/tests/examples/test_sports_tournament_scheduling.py +0 -0
  144. {nucs-7.0.0 → nucs-7.2.0}/tests/examples/test_sudokus.py +0 -0
  145. {nucs-7.0.0 → nucs-7.2.0}/tests/examples/test_tsp.py +0 -0
  146. {nucs-7.0.0/tests/propagators → nucs-7.2.0/tests/heuristics}/__init__.py +0 -0
  147. {nucs-7.0.0 → nucs-7.2.0}/tests/heuristics/test_max_value_dom_heuristic.py +0 -0
  148. {nucs-7.0.0 → nucs-7.2.0}/tests/heuristics/test_mid_value_dom_heuristic.py +0 -0
  149. {nucs-7.0.0 → nucs-7.2.0}/tests/heuristics/test_min_value_dom_heuristic.py +0 -0
  150. {nucs-7.0.0/tests/solvers → nucs-7.2.0/tests/problems}/__init__.py +0 -0
  151. {nucs-7.0.0 → nucs-7.2.0}/tests/problems/test_circuit_problem.py +0 -0
  152. {nucs-7.0.0 → nucs-7.2.0}/tests/problems/test_permutation_problem.py +0 -0
  153. {nucs-7.0.0 → nucs-7.2.0}/tests/problems/test_problem.py +0 -0
  154. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/propagator_test.py +0 -0
  155. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_abs_eq.py +0 -0
  156. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_affine_eq.py +0 -0
  157. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_affine_geq.py +0 -0
  158. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_affine_leq.py +0 -0
  159. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_alldifferent.py +0 -0
  160. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_count_eq.py +0 -0
  161. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_count_eq_c.py +0 -0
  162. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_count_leq_c.py +0 -0
  163. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_element_eq.py +0 -0
  164. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_element_l_eq.py +0 -0
  165. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_element_l_eq_c.py +0 -0
  166. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_equiv_eq.py +0 -0
  167. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_gcc.py +0 -0
  168. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_lexicographic_leq.py +0 -0
  169. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_max_eq.py +0 -0
  170. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_max_leq.py +0 -0
  171. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_min_eq.py +0 -0
  172. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_min_geq.py +0 -0
  173. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_no_sub_cycle.py +0 -0
  174. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_relation.py +0 -0
  175. {nucs-7.0.0 → nucs-7.2.0}/tests/propagators/test_scc.py +0 -0
  176. {nucs-7.0.0 → nucs-7.2.0}/tests/solvers/test_backtrack_solver.py +0 -0
  177. {nucs-7.0.0 → nucs-7.2.0}/tests/solvers/test_multiprocessing_solver.py +0 -0
  178. {nucs-7.0.0 → nucs-7.2.0}/tests/test_heaps.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: NuCS
3
- Version: 7.0.0
3
+ Version: 7.2.0
4
4
  Summary: A Numpy and Numba based Python library for solving Constraint Satisfaction Problems over finite domains
5
5
  Author-email: Yan Georget <yan.georget@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/yangeorget/nucs
@@ -26,6 +26,9 @@ nucs/examples/bibd/bibd_problem.py
26
26
  nucs/examples/donald/__init__.py
27
27
  nucs/examples/donald/__main__.py
28
28
  nucs/examples/donald/donald_problem.py
29
+ nucs/examples/employee_scheduling/__init__.py
30
+ nucs/examples/employee_scheduling/__main__.py
31
+ nucs/examples/employee_scheduling/employee_scheduling_problem.py
29
32
  nucs/examples/golomb/__init__.py
30
33
  nucs/examples/golomb/__main__.py
31
34
  nucs/examples/golomb/golomb_problem.py
@@ -88,6 +91,7 @@ nucs/propagators/alldifferent_propagator.py
88
91
  nucs/propagators/and_eq_propagator.py
89
92
  nucs/propagators/count_eq_c_propagator.py
90
93
  nucs/propagators/count_eq_propagator.py
94
+ nucs/propagators/count_geq_c_propagator.py
91
95
  nucs/propagators/count_leq_c_propagator.py
92
96
  nucs/propagators/dummy_propagator.py
93
97
  nucs/propagators/element_eq_propagator.py
@@ -118,10 +122,12 @@ nucs/solvers/shaving_consistency_algorithm.py
118
122
  nucs/solvers/solver.py
119
123
  tests/__init__.py
120
124
  tests/test_heaps.py
125
+ tests/examples/__init__.py
121
126
  tests/examples/test_all_interval_series.py
122
127
  tests/examples/test_alpha.py
123
128
  tests/examples/test_bibd.py
124
129
  tests/examples/test_donald.py
130
+ tests/examples/test_employee_scheduling.py
125
131
  tests/examples/test_golomb.py
126
132
  tests/examples/test_knapsack.py
127
133
  tests/examples/test_latin_square.py
@@ -150,6 +156,7 @@ tests/propagators/test_affine_leq.py
150
156
  tests/propagators/test_alldifferent.py
151
157
  tests/propagators/test_count_eq.py
152
158
  tests/propagators/test_count_eq_c.py
159
+ tests/propagators/test_count_geq_c.py
153
160
  tests/propagators/test_count_leq_c.py
154
161
  tests/propagators/test_element_eq.py
155
162
  tests/propagators/test_element_l_eq.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: NuCS
3
- Version: 7.0.0
3
+ Version: 7.2.0
4
4
  Summary: A Numpy and Numba based Python library for solving Constraint Satisfaction Problems over finite domains
5
5
  Author-email: Yan Georget <yan.georget@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/yangeorget/nucs
@@ -6,8 +6,8 @@ project = 'NuCS'
6
6
  copyright = '2024-2025, Yan Georget'
7
7
  author = 'Yan Georget'
8
8
 
9
- release = '7.0.0'
10
- version = '7.0.0'
9
+ release = '7.2.0'
10
+ version = '7.2.0'
11
11
 
12
12
  # -- General configuration
13
13
 
@@ -0,0 +1,31 @@
1
+ ###############################################################################
2
+ # __ _ _____ _____
3
+ # | \ | | / ____| / ____|
4
+ # | \| | _ _ | | | (___
5
+ # | . ` | | | | | | | \___ \
6
+ # | |\ | | |_| | | |____ ____) |
7
+ # |_| \_| \__,_| \_____| |_____/
8
+ #
9
+ # Fast constraint solving in Python - https://github.com/yangeorget/nucs
10
+ #
11
+ # Copyright 2024-2025 - Yan Georget
12
+ ###############################################################################
13
+ from nucs.constants import OPTIM_MODES, OPTIM_PRUNE
14
+ from nucs.examples.default_argument_parser import DefaultArgumentParser
15
+ from nucs.examples.employee_scheduling.employee_scheduling_problem import EmployeeSchedulingProblem
16
+ from nucs.heuristics.heuristics import DOM_HEURISTIC_MAX_VALUE
17
+ from nucs.solvers.backtrack_solver import BacktrackSolver
18
+
19
+ # Run with the following command (the second run is much faster because the code has been compiled):
20
+ # NUMBA_CACHE_DIR=.numba/cache python -m nucs.examples.employee_scheduling
21
+ if __name__ == "__main__":
22
+ parser = DefaultArgumentParser()
23
+ parser.add_argument("--opt_mode", choices=OPTIM_MODES, default=OPTIM_PRUNE)
24
+ args = parser.parse_args()
25
+ problem = EmployeeSchedulingProblem()
26
+ solver = BacktrackSolver(problem, dom_heuristic_idx=DOM_HEURISTIC_MAX_VALUE, log_level=args.log_level)
27
+ solution = solver.maximize(problem.satisfied_request_nb, mode=args.opt_mode)
28
+ if args.stats:
29
+ solver.print_statistics()
30
+ if args.display:
31
+ problem.print_solution(solution)
@@ -0,0 +1,107 @@
1
+ ###############################################################################
2
+ # __ _ _____ _____
3
+ # | \ | | / ____| / ____|
4
+ # | \| | _ _ | | | (___
5
+ # | . ` | | | | | | | \___ \
6
+ # | |\ | | |_| | | |____ ____) |
7
+ # |_| \_| \__,_| \_____| |_____/
8
+ #
9
+ # Fast constraint solving in Python - https://github.com/yangeorget/nucs
10
+ #
11
+ # Copyright 2024-2025 - Yan Georget
12
+ ###############################################################################
13
+ from typing import Any, List
14
+
15
+ from numpy.typing import NDArray
16
+
17
+ from nucs.problems.problem import Problem
18
+ from nucs.propagators.propagators import ALG_COUNT_EQ, ALG_COUNT_EQ_C, ALG_COUNT_LEQ_C
19
+
20
+
21
+ # TODO: GCC instead of booleans
22
+ # TODO: get rid of count variables, use count_leq and count_geq
23
+ # TODO: use custom heuristic (cf requests)
24
+ class EmployeeSchedulingProblem(Problem):
25
+ """
26
+ See https://developers.google.com/optimization/scheduling/employee_scheduling.
27
+ """
28
+
29
+ def shift_index(self, day: int, shift: int, nurse: int) -> int:
30
+ return day * self.shift_nb * self.nurse_nb + shift * self.nurse_nb + nurse
31
+
32
+ def nurses(self, day: int, shift: int) -> List[int]:
33
+ start_shift = self.shift_index(day, shift, 0)
34
+ return list(range(start_shift, start_shift + self.nurse_nb))
35
+
36
+ def shifts(self, day: int, nurse: int) -> List[int]:
37
+ start_shift = self.shift_index(day, 0, nurse)
38
+ return list(
39
+ range(
40
+ start_shift,
41
+ start_shift + self.shift_nb * self.nurse_nb,
42
+ self.nurse_nb,
43
+ )
44
+ )
45
+
46
+ def __init__(self) -> None:
47
+ """
48
+ Initializes the problem.
49
+ """
50
+ self.day_nb = 7
51
+ self.shift_nb = 3
52
+ self.nurse_nb = 5
53
+ self.shift_total_nb = self.day_nb * self.shift_nb * self.nurse_nb
54
+ self.shift_requests_nds = [
55
+ [[0, 0, 1], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 1]],
56
+ [[0, 0, 0], [0, 0, 0], [0, 1, 0], [0, 1, 0], [1, 0, 0], [0, 0, 0], [0, 0, 1]],
57
+ [[0, 1, 0], [0, 1, 0], [0, 0, 0], [1, 0, 0], [0, 0, 0], [0, 1, 0], [0, 0, 0]],
58
+ [[0, 0, 1], [0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 0], [1, 0, 0], [0, 0, 0]],
59
+ [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 0]],
60
+ ]
61
+ shift_requests_dsn = [
62
+ self.shift_requests_nds[n][d][s]
63
+ for d in range(self.day_nb)
64
+ for s in range(self.shift_nb)
65
+ for n in range(self.nurse_nb)
66
+ ]
67
+ min_shift_count_per_nurse = (self.shift_nb * self.day_nb) // self.nurse_nb
68
+ max_shift_count_per_nurse = min_shift_count_per_nurse + (
69
+ 0 if self.shift_nb * self.day_nb % self.nurse_nb == 0 else 1
70
+ )
71
+ super().__init__([(0, 1)] * self.shift_total_nb) # the boolean variables for shifts
72
+ self.add_variables(
73
+ [(min_shift_count_per_nurse, max_shift_count_per_nurse)] * self.nurse_nb
74
+ ) # the number of shifts per nurse
75
+ self.satisfied_request_nb = self.add_variable((0, self.shift_total_nb)) # the number of satisfied requests
76
+ self.add_propagators(
77
+ [(self.nurses(d, s), ALG_COUNT_EQ_C, [1, 1]) for d in range(self.day_nb) for s in range(self.shift_nb)]
78
+ )
79
+ self.add_propagators(
80
+ [(self.shifts(d, n), ALG_COUNT_LEQ_C, [1, 1]) for d in range(self.day_nb) for n in range(self.nurse_nb)]
81
+ )
82
+ self.add_propagators(
83
+ [
84
+ (list(range(n, self.shift_total_nb + self.nurse_nb, self.nurse_nb)), ALG_COUNT_EQ, [1])
85
+ for n in range(self.nurse_nb)
86
+ ]
87
+ )
88
+ self.add_propagator(
89
+ (
90
+ [index for index in range(0, self.shift_total_nb) if shift_requests_dsn[index]]
91
+ + [self.satisfied_request_nb],
92
+ ALG_COUNT_EQ,
93
+ [1],
94
+ )
95
+ )
96
+
97
+ def solution_as_printable(self, solution: NDArray) -> Any:
98
+ return {
99
+ d: [
100
+ [
101
+ (("W" if self.shift_requests_nds[n][d][s] else "w") if solution[self.shift_index(d, s, n)] else " ")
102
+ for n in range(self.nurse_nb)
103
+ ]
104
+ for s in range(self.shift_nb)
105
+ ]
106
+ for d in range(self.day_nb)
107
+ }
@@ -12,7 +12,7 @@
12
12
  ###############################################################################
13
13
  import copy
14
14
  import logging
15
- from typing import Any, List, Optional, Self, Tuple, Union
15
+ from typing import Any, List, Optional, Self, Sequence, Tuple, Union
16
16
 
17
17
  import numpy as np
18
18
  from numba import njit
@@ -114,7 +114,7 @@ class Problem:
114
114
 
115
115
  def add_variables(
116
116
  self,
117
- domains: List[Union[int, Tuple[int, int]]],
117
+ domains: Sequence[Union[int, Tuple[int, int]]],
118
118
  variables: Optional[List[int]] = None,
119
119
  offsets: Optional[List[int]] = None,
120
120
  ) -> int:
@@ -39,7 +39,7 @@ def get_triggers_affine_eq(n: int, dom_idx: int, parameters: NDArray) -> int:
39
39
  @njit(cache=True)
40
40
  def compute_domains_affine_eq(domains: NDArray, parameters: NDArray) -> int:
41
41
  """
42
- Implements Sigma_i a_i * x_i = a_{n-1}.
42
+ Implements Sigma_i a_i * x_i = a_{n}.
43
43
  :param domains: the domains of the variables, x is an alias for domains
44
44
  :param parameters: the parameters of the propagator, a is an alias for parameters
45
45
  :return: the status of the propagation (consistency, inconsistency or entailment) as an int
@@ -47,7 +47,7 @@ def get_triggers_affine_geq(n: int, dom_idx: int, parameters: NDArray) -> int:
47
47
  @njit(cache=True)
48
48
  def compute_domains_affine_geq(domains: NDArray, parameters: NDArray) -> int:
49
49
  """
50
- Implements Sigma_i a_i * x_i >= a_{n-1}.
50
+ Implements Sigma_i a_i * x_i >= a_{n}.
51
51
  :param domains: the domains of the variables, x is an alias for domains
52
52
  :param parameters: the parameters of the propagator, a is an alias for parameters
53
53
  :return: the status of the propagation (consistency, inconsistency or entailment) as an int
@@ -47,7 +47,7 @@ def get_triggers_affine_leq(n: int, dom_idx: int, parameters: NDArray) -> int:
47
47
  @njit(cache=True)
48
48
  def compute_domains_affine_leq(domains: NDArray, parameters: NDArray) -> int:
49
49
  """
50
- Implements Sigma_i a_i * x_i <= a_{n-1}.
50
+ Implements Sigma_i a_i * x_i <= a_{n}.
51
51
  :param domains: the domains of the variables, x is an alias for domains
52
52
  :param parameters: the parameters of the propagator, a is an alias for parameters
53
53
  :return: the status of the propagation (consistency, inconsistency or entailment) as an int
@@ -0,0 +1,65 @@
1
+ ###############################################################################
2
+ # __ _ _____ _____
3
+ # | \ | | / ____| / ____|
4
+ # | \| | _ _ | | | (___
5
+ # | . ` | | | | | | | \___ \
6
+ # | |\ | | |_| | | |____ ____) |
7
+ # |_| \_| \__,_| \_____| |_____/
8
+ #
9
+ # Fast constraint solving in Python - https://github.com/yangeorget/nucs
10
+ #
11
+ # Copyright 2024-2025 - Yan Georget
12
+ ###############################################################################
13
+ from numba import njit # type: ignore
14
+ from numpy.typing import NDArray
15
+
16
+ from nucs.constants import EVENT_MASK_MIN_MAX, MAX, MIN, PROP_CONSISTENCY, PROP_ENTAILMENT, PROP_INCONSISTENCY
17
+
18
+
19
+ def get_complexity_count_geq_c(n: int, parameters: NDArray) -> float:
20
+ """
21
+ Returns the time complexity of the propagator as a float.
22
+ :param n: the number of variables
23
+ :param parameters: the parameters, unused here
24
+ :return: a float
25
+ """
26
+ return n
27
+
28
+
29
+ @njit(cache=True)
30
+ def get_triggers_count_geq_c(n: int, dom_idx: int, parameters: NDArray) -> int:
31
+ """
32
+ This propagator is triggered whenever there is a change in the domain of a variable.
33
+ :param parameters: the parameters, unused here
34
+ :return: an array of triggers
35
+ """
36
+ return EVENT_MASK_MIN_MAX
37
+
38
+
39
+ @njit(cache=True)
40
+ def compute_domains_count_geq_c(domains: NDArray, parameters: NDArray) -> int:
41
+ """
42
+ Implements Sigma_i (x_i == a) >= c.
43
+ :param domains: the domains of the variables, x is an alias for domains
44
+ :param parameters: the parameters of the propagator, a is the first parameter, c is the second parameter
45
+ :return: the status of the propagation (consistency, inconsistency or entailment) as an int
46
+ """
47
+ a = parameters[0]
48
+ c = parameters[1]
49
+ count_max = len(domains)
50
+ count_min = 0
51
+ for domain in domains:
52
+ if domain[MIN] > a or domain[MAX] < a:
53
+ count_max -= 1
54
+ if count_max < c:
55
+ return PROP_INCONSISTENCY
56
+ elif domain[MIN] == a and domain[MAX] == a:
57
+ count_min += 1
58
+ if count_min >= c:
59
+ return PROP_ENTAILMENT
60
+ if count_max == c: # we cannot have more domains different from a
61
+ for domain in domains:
62
+ if domain[MIN] <= a <= domain[MAX]:
63
+ domain[:] = a
64
+ return PROP_ENTAILMENT
65
+ return PROP_CONSISTENCY
@@ -51,12 +51,12 @@ def compute_domains_count_leq_c(domains: NDArray, parameters: NDArray) -> int:
51
51
  for domain in domains:
52
52
  if domain[MIN] > a or domain[MAX] < a:
53
53
  count_max -= 1
54
+ if count_max <= c:
55
+ return PROP_ENTAILMENT
54
56
  elif domain[MIN] == a and domain[MAX] == a:
55
57
  count_min += 1
56
58
  if count_min > c:
57
59
  return PROP_INCONSISTENCY
58
- if count_max <= c:
59
- return PROP_ENTAILMENT
60
60
  if count_min == c: # we cannot have more domains equal to a
61
61
  all_different = True
62
62
  for domain in domains:
@@ -48,6 +48,11 @@ from nucs.propagators.count_eq_propagator import (
48
48
  get_complexity_count_eq,
49
49
  get_triggers_count_eq,
50
50
  )
51
+ from nucs.propagators.count_geq_c_propagator import (
52
+ compute_domains_count_geq_c,
53
+ get_complexity_count_geq_c,
54
+ get_triggers_count_geq_c,
55
+ )
51
56
  from nucs.propagators.count_leq_c_propagator import (
52
57
  compute_domains_count_leq_c,
53
58
  get_complexity_count_leq_c,
@@ -140,6 +145,7 @@ ALG_ALLDIFFERENT = register_propagator(
140
145
  )
141
146
  ALG_COUNT_EQ = register_propagator(get_triggers_count_eq, get_complexity_count_eq, compute_domains_count_eq)
142
147
  ALG_COUNT_EQ_C = register_propagator(get_triggers_count_eq_c, get_complexity_count_eq_c, compute_domains_count_eq_c)
148
+ ALG_COUNT_GEQ_C = register_propagator(get_triggers_count_geq_c, get_complexity_count_geq_c, compute_domains_count_geq_c)
143
149
  ALG_COUNT_LEQ_C = register_propagator(get_triggers_count_leq_c, get_complexity_count_leq_c, compute_domains_count_leq_c)
144
150
  ALG_DUMMY = register_propagator(get_triggers_dummy, get_complexity_dummy, compute_domains_dummy)
145
151
  ALG_ELEMENT_EQ = register_propagator(get_triggers_element_eq, get_complexity_element_eq, compute_domains_element_eq)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name="NuCS"
3
- version="7.0.0"
3
+ version="7.2.0"
4
4
  authors = [
5
5
  { name="Yan Georget", email="yan.georget@gmail.com" },
6
6
  ]
@@ -0,0 +1,27 @@
1
+ ###############################################################################
2
+ # __ _ _____ _____
3
+ # | \ | | / ____| / ____|
4
+ # | \| | _ _ | | | (___
5
+ # | . ` | | | | | | | \___ \
6
+ # | |\ | | |_| | | |____ ____) |
7
+ # |_| \_| \__,_| \_____| |_____/
8
+ #
9
+ # Fast constraint solving in Python - https://github.com/yangeorget/nucs
10
+ #
11
+ # Copyright 2024-2025 - Yan Georget
12
+ ###############################################################################
13
+ from nucs.examples.employee_scheduling.employee_scheduling_problem import EmployeeSchedulingProblem
14
+
15
+
16
+ class TestEmployeeScheduling:
17
+ def test_nurses(self) -> None:
18
+ assert EmployeeSchedulingProblem().nurses(0, 0) == [0, 1, 2, 3, 4]
19
+ assert EmployeeSchedulingProblem().nurses(0, 1) == [5, 6, 7, 8, 9]
20
+ assert EmployeeSchedulingProblem().nurses(1, 0) == [15, 16, 17, 18, 19]
21
+ assert EmployeeSchedulingProblem().nurses(1, 1) == [20, 21, 22, 23, 24]
22
+
23
+ def test_shifts(self) -> None:
24
+ assert EmployeeSchedulingProblem().shifts(0, 0) == [0, 5, 10]
25
+ assert EmployeeSchedulingProblem().shifts(0, 1) == [1, 6, 11]
26
+ assert EmployeeSchedulingProblem().shifts(1, 0) == [15, 20, 25]
27
+ assert EmployeeSchedulingProblem().shifts(1, 1) == [16, 21, 26]
File without changes
@@ -0,0 +1,55 @@
1
+ ###############################################################################
2
+ # __ _ _____ _____
3
+ # | \ | | / ____| / ____|
4
+ # | \| | _ _ | | | (___
5
+ # | . ` | | | | | | | \___ \
6
+ # | |\ | | |_| | | |____ ____) |
7
+ # |_| \_| \__,_| \_____| |_____/
8
+ #
9
+ # Fast constraint solving in Python - https://github.com/yangeorget/nucs
10
+ #
11
+ # Copyright 2024-2025 - Yan Georget
12
+ ###############################################################################
13
+ from typing import List, Optional, Tuple, Union
14
+
15
+ import pytest
16
+
17
+ from nucs.constants import PROP_CONSISTENCY, PROP_ENTAILMENT, PROP_INCONSISTENCY
18
+ from nucs.propagators.count_geq_c_propagator import compute_domains_count_geq_c
19
+ from tests.propagators.propagator_test import PropagatorTest
20
+
21
+
22
+ class TestCountGeqC(PropagatorTest):
23
+ @pytest.mark.parametrize(
24
+ "domains,parameters,consistency_result,expected_domains",
25
+ [
26
+ (
27
+ [(1, 4), (3, 5), (3, 6), (6, 8), 3, 5],
28
+ [9, 1],
29
+ PROP_INCONSISTENCY,
30
+ None,
31
+ ),
32
+ (
33
+ [(1, 4), (3, 5), (3, 5), (6, 8), 3, 5],
34
+ [5, 3],
35
+ PROP_ENTAILMENT,
36
+ [[1, 4], [5, 5], [5, 5], [6, 8], [3, 3], [5, 5]],
37
+ ),
38
+ (
39
+ [(1, 4), (3, 5), (3, 6), (6, 8), 3, 5],
40
+ [5, 2],
41
+ PROP_CONSISTENCY,
42
+ [[1, 4], [3, 5], [3, 6], [6, 8], [3, 3], [5, 5]],
43
+ ),
44
+ ],
45
+ )
46
+ def test_compute_domains(
47
+ self,
48
+ domains: List[Union[int, Tuple[int, int]]],
49
+ parameters: List[int],
50
+ consistency_result: int,
51
+ expected_domains: Optional[List[List[int]]],
52
+ ) -> None:
53
+ self.assert_compute_domains(
54
+ compute_domains_count_geq_c, domains, parameters, consistency_result, expected_domains
55
+ )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes