NUCS 4.0.0__tar.gz → 4.2.0__tar.gz

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