NUCS 0.1__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 (40) hide show
  1. nucs-0.1/LICENSE.md +21 -0
  2. nucs-0.1/NUCS.egg-info/PKG-INFO +78 -0
  3. nucs-0.1/NUCS.egg-info/SOURCES.txt +38 -0
  4. nucs-0.1/NUCS.egg-info/dependency_links.txt +1 -0
  5. nucs-0.1/NUCS.egg-info/requires.txt +2 -0
  6. nucs-0.1/NUCS.egg-info/top_level.txt +1 -0
  7. nucs-0.1/PKG-INFO +78 -0
  8. nucs-0.1/README.md +63 -0
  9. nucs-0.1/nucs/__init__.py +0 -0
  10. nucs-0.1/nucs/heuristics/heuristic.py +24 -0
  11. nucs-0.1/nucs/heuristics/variable_heuristic.py +97 -0
  12. nucs-0.1/nucs/memory.py +73 -0
  13. nucs-0.1/nucs/problems/__init__.py +0 -0
  14. nucs-0.1/nucs/problems/alpha_problem.py +107 -0
  15. nucs-0.1/nucs/problems/bibd_problem.py +49 -0
  16. nucs-0.1/nucs/problems/golomb_problem.py +76 -0
  17. nucs-0.1/nucs/problems/problem.py +271 -0
  18. nucs-0.1/nucs/problems/queens_problem.py +22 -0
  19. nucs-0.1/nucs/problems/schur_lemma_problem.py +29 -0
  20. nucs-0.1/nucs/problems/sudoku_problem.py +46 -0
  21. nucs-0.1/nucs/propagators/__init__.py +0 -0
  22. nucs-0.1/nucs/propagators/affine_eq_propagator.py +55 -0
  23. nucs-0.1/nucs/propagators/affine_geq_propagator.py +52 -0
  24. nucs-0.1/nucs/propagators/affine_leq_propagator.py +52 -0
  25. nucs-0.1/nucs/propagators/alldifferent_propagator.py +180 -0
  26. nucs-0.1/nucs/propagators/count_eq_propagator.py +47 -0
  27. nucs-0.1/nucs/propagators/dummy_propagator.py +21 -0
  28. nucs-0.1/nucs/propagators/exactly_eq_propagator.py +44 -0
  29. nucs-0.1/nucs/propagators/lexicographic_leq_propagator.py +139 -0
  30. nucs-0.1/nucs/propagators/max_eq_propagator.py +36 -0
  31. nucs-0.1/nucs/propagators/max_leq_propagator.py +46 -0
  32. nucs-0.1/nucs/propagators/min_eq_propagator.py +36 -0
  33. nucs-0.1/nucs/propagators/min_geq_propagator.py +46 -0
  34. nucs-0.1/nucs/propagators/propagators.py +135 -0
  35. nucs-0.1/nucs/solvers/__init__.py +0 -0
  36. nucs-0.1/nucs/solvers/backtrack_solver.py +105 -0
  37. nucs-0.1/nucs/solvers/solver.py +41 -0
  38. nucs-0.1/nucs/statistics.py +44 -0
  39. nucs-0.1/pyproject.toml +31 -0
  40. nucs-0.1/setup.cfg +4 -0
nucs-0.1/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Yan Georget
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,78 @@
1
+ Metadata-Version: 2.1
2
+ Name: NUCS
3
+ Version: 0.1
4
+ Summary: A Numpy and Numba based Python library for solving Constraint Satifaction Problems
5
+ Author-email: Yan Georget <yan.georget@gmail.com>
6
+ Project-URL: Homepage, https://github.com/yangeorget/nucs
7
+ Project-URL: Issues, https://github.com/yangeorget/nucs
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.8
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE.md
13
+ Requires-Dist: numba==0.60.0
14
+ Requires-Dist: numpy==2.0.1
15
+
16
+ # NUCS
17
+
18
+ ## TLDR
19
+ NUCS is a Python library for solving Constraint Satisfaction and Optimization Problems.
20
+
21
+ NUCS is powered by Numpy (https://numpy.org/) and Numba (https://numba.pydata.org/).
22
+
23
+ NUCS is fast and easy to use.
24
+
25
+
26
+ ## How to use NUCS ?
27
+ It is very simple to get started with NUCS.
28
+ Either clone the Github repository or install the package.
29
+
30
+ ### Clone the NUCS Github repository
31
+ Let's install NUCS from the source:
32
+ ```
33
+ git clone https://github.com/yangeorget/nucs.git
34
+ pip install -r requirements.txt
35
+ ```
36
+
37
+ From there, you can launch some NUCS examples.
38
+ Note that the second run will be much faster since the Python code will have been compiled.
39
+
40
+ #### Run the NUCS tests
41
+ ```
42
+ NUMBA_CACHE_DIR=.numba/cache PYTHONPATH=. pytest tests/
43
+ ```
44
+
45
+ #### Run some examples
46
+ Find all solutions to the 12-queens problem:
47
+ ```
48
+ NUMBA_CACHE_DIR=.numba/cache PYTHONPATH=. python3 tests/examples/test_queens.py -n 12
49
+ ```
50
+
51
+ Find the optimal solution to the Golomb ruler problem with 10 marks:
52
+ ```
53
+ NUMBA_CACHE_DIR=.numba/cache PYTHONPATH=. python3 tests/examples/test_golomb.py -n 10
54
+ ```
55
+
56
+ ### Install the NUCS package
57
+ ```
58
+ pip install nucs
59
+ ````
60
+
61
+ ## Why Python ?
62
+ NUCS is a Python library leveraging Numpy and Numba.
63
+
64
+ Python is a powerful and flexible programing language that allows to express complex problems in a few lines of code.
65
+
66
+ Numpy brings the computational power of languages like C and Fortran to Python, a language much easier to learn and use.
67
+
68
+ Numba translates Python functions to optimized machine code at runtime using the industry-standard LLVM compiler library.
69
+ Numba-compiled numerical algorithms in Python can approach the speeds of C or FORTRAN.
70
+
71
+ ## Architecture
72
+
73
+ ## Speed matters
74
+
75
+ ## Other constraint solvers in Python
76
+ - python-constraint
77
+ - CCPMpy
78
+ - PyCSP
@@ -0,0 +1,38 @@
1
+ LICENSE.md
2
+ README.md
3
+ pyproject.toml
4
+ NUCS.egg-info/PKG-INFO
5
+ NUCS.egg-info/SOURCES.txt
6
+ NUCS.egg-info/dependency_links.txt
7
+ NUCS.egg-info/requires.txt
8
+ NUCS.egg-info/top_level.txt
9
+ nucs/__init__.py
10
+ nucs/memory.py
11
+ nucs/statistics.py
12
+ nucs/heuristics/heuristic.py
13
+ nucs/heuristics/variable_heuristic.py
14
+ nucs/problems/__init__.py
15
+ nucs/problems/alpha_problem.py
16
+ nucs/problems/bibd_problem.py
17
+ nucs/problems/golomb_problem.py
18
+ nucs/problems/problem.py
19
+ nucs/problems/queens_problem.py
20
+ nucs/problems/schur_lemma_problem.py
21
+ nucs/problems/sudoku_problem.py
22
+ nucs/propagators/__init__.py
23
+ nucs/propagators/affine_eq_propagator.py
24
+ nucs/propagators/affine_geq_propagator.py
25
+ nucs/propagators/affine_leq_propagator.py
26
+ nucs/propagators/alldifferent_propagator.py
27
+ nucs/propagators/count_eq_propagator.py
28
+ nucs/propagators/dummy_propagator.py
29
+ nucs/propagators/exactly_eq_propagator.py
30
+ nucs/propagators/lexicographic_leq_propagator.py
31
+ nucs/propagators/max_eq_propagator.py
32
+ nucs/propagators/max_leq_propagator.py
33
+ nucs/propagators/min_eq_propagator.py
34
+ nucs/propagators/min_geq_propagator.py
35
+ nucs/propagators/propagators.py
36
+ nucs/solvers/__init__.py
37
+ nucs/solvers/backtrack_solver.py
38
+ nucs/solvers/solver.py
@@ -0,0 +1,2 @@
1
+ numba==0.60.0
2
+ numpy==2.0.1
@@ -0,0 +1 @@
1
+ nucs
nucs-0.1/PKG-INFO ADDED
@@ -0,0 +1,78 @@
1
+ Metadata-Version: 2.1
2
+ Name: NUCS
3
+ Version: 0.1
4
+ Summary: A Numpy and Numba based Python library for solving Constraint Satifaction Problems
5
+ Author-email: Yan Georget <yan.georget@gmail.com>
6
+ Project-URL: Homepage, https://github.com/yangeorget/nucs
7
+ Project-URL: Issues, https://github.com/yangeorget/nucs
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.8
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE.md
13
+ Requires-Dist: numba==0.60.0
14
+ Requires-Dist: numpy==2.0.1
15
+
16
+ # NUCS
17
+
18
+ ## TLDR
19
+ NUCS is a Python library for solving Constraint Satisfaction and Optimization Problems.
20
+
21
+ NUCS is powered by Numpy (https://numpy.org/) and Numba (https://numba.pydata.org/).
22
+
23
+ NUCS is fast and easy to use.
24
+
25
+
26
+ ## How to use NUCS ?
27
+ It is very simple to get started with NUCS.
28
+ Either clone the Github repository or install the package.
29
+
30
+ ### Clone the NUCS Github repository
31
+ Let's install NUCS from the source:
32
+ ```
33
+ git clone https://github.com/yangeorget/nucs.git
34
+ pip install -r requirements.txt
35
+ ```
36
+
37
+ From there, you can launch some NUCS examples.
38
+ Note that the second run will be much faster since the Python code will have been compiled.
39
+
40
+ #### Run the NUCS tests
41
+ ```
42
+ NUMBA_CACHE_DIR=.numba/cache PYTHONPATH=. pytest tests/
43
+ ```
44
+
45
+ #### Run some examples
46
+ Find all solutions to the 12-queens problem:
47
+ ```
48
+ NUMBA_CACHE_DIR=.numba/cache PYTHONPATH=. python3 tests/examples/test_queens.py -n 12
49
+ ```
50
+
51
+ Find the optimal solution to the Golomb ruler problem with 10 marks:
52
+ ```
53
+ NUMBA_CACHE_DIR=.numba/cache PYTHONPATH=. python3 tests/examples/test_golomb.py -n 10
54
+ ```
55
+
56
+ ### Install the NUCS package
57
+ ```
58
+ pip install nucs
59
+ ````
60
+
61
+ ## Why Python ?
62
+ NUCS is a Python library leveraging Numpy and Numba.
63
+
64
+ Python is a powerful and flexible programing language that allows to express complex problems in a few lines of code.
65
+
66
+ Numpy brings the computational power of languages like C and Fortran to Python, a language much easier to learn and use.
67
+
68
+ Numba translates Python functions to optimized machine code at runtime using the industry-standard LLVM compiler library.
69
+ Numba-compiled numerical algorithms in Python can approach the speeds of C or FORTRAN.
70
+
71
+ ## Architecture
72
+
73
+ ## Speed matters
74
+
75
+ ## Other constraint solvers in Python
76
+ - python-constraint
77
+ - CCPMpy
78
+ - PyCSP
nucs-0.1/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # NUCS
2
+
3
+ ## TLDR
4
+ NUCS is a Python library for solving Constraint Satisfaction and Optimization Problems.
5
+
6
+ NUCS is powered by Numpy (https://numpy.org/) and Numba (https://numba.pydata.org/).
7
+
8
+ NUCS is fast and easy to use.
9
+
10
+
11
+ ## How to use NUCS ?
12
+ It is very simple to get started with NUCS.
13
+ Either clone the Github repository or install the package.
14
+
15
+ ### Clone the NUCS Github repository
16
+ Let's install NUCS from the source:
17
+ ```
18
+ git clone https://github.com/yangeorget/nucs.git
19
+ pip install -r requirements.txt
20
+ ```
21
+
22
+ From there, you can launch some NUCS examples.
23
+ Note that the second run will be much faster since the Python code will have been compiled.
24
+
25
+ #### Run the NUCS tests
26
+ ```
27
+ NUMBA_CACHE_DIR=.numba/cache PYTHONPATH=. pytest tests/
28
+ ```
29
+
30
+ #### Run some examples
31
+ Find all solutions to the 12-queens problem:
32
+ ```
33
+ NUMBA_CACHE_DIR=.numba/cache PYTHONPATH=. python3 tests/examples/test_queens.py -n 12
34
+ ```
35
+
36
+ Find the optimal solution to the Golomb ruler problem with 10 marks:
37
+ ```
38
+ NUMBA_CACHE_DIR=.numba/cache PYTHONPATH=. python3 tests/examples/test_golomb.py -n 10
39
+ ```
40
+
41
+ ### Install the NUCS package
42
+ ```
43
+ pip install nucs
44
+ ````
45
+
46
+ ## Why Python ?
47
+ NUCS is a Python library leveraging Numpy and Numba.
48
+
49
+ Python is a powerful and flexible programing language that allows to express complex problems in a few lines of code.
50
+
51
+ Numpy brings the computational power of languages like C and Fortran to Python, a language much easier to learn and use.
52
+
53
+ Numba translates Python functions to optimized machine code at runtime using the industry-standard LLVM compiler library.
54
+ Numba-compiled numerical algorithms in Python can approach the speeds of C or FORTRAN.
55
+
56
+ ## Architecture
57
+
58
+ ## Speed matters
59
+
60
+ ## Other constraint solvers in Python
61
+ - python-constraint
62
+ - CCPMpy
63
+ - PyCSP
File without changes
@@ -0,0 +1,24 @@
1
+ from abc import abstractmethod
2
+ from typing import List
3
+
4
+ from numpy.typing import NDArray
5
+
6
+
7
+ class Heuristic:
8
+ """
9
+ Makes a choice.
10
+ A choice can be more complex than just instantiating a variable.
11
+ """
12
+
13
+ @abstractmethod
14
+ def choose(
15
+ self, choice_points: List[NDArray], shr_domains: NDArray, shr_domain_changes: NDArray, dom_indices: NDArray
16
+ ) -> None:
17
+ """
18
+ Makes a choice.
19
+ :param choice_points: the choice point stack
20
+ :param shr_domains: the shared domains of the problem
21
+ :param shr_domain_changes: an array of shared domain changes
22
+ :param dom_indices: the domain indices of the problem variables
23
+ """
24
+ pass
@@ -0,0 +1,97 @@
1
+ import sys
2
+ from typing import Callable, List
3
+
4
+ from numba import njit # type: ignore
5
+ from numpy.typing import NDArray
6
+
7
+ from nucs.heuristics.heuristic import Heuristic
8
+ from nucs.memory import MAX, MIN
9
+
10
+
11
+ class VariableHeuristic(Heuristic):
12
+ """
13
+ Chooses a variable and one or several values for this variable.
14
+ """
15
+
16
+ def __init__(self, variable_heuristic: Callable, domain_heuristic: Callable):
17
+ """
18
+ Inits the heuristic.
19
+ :param variable_heuristic: a function for choosing the variable
20
+ :param domain_heuristic: a function for choosing a new domain for this variable
21
+ """
22
+ self.variable_heuristic = variable_heuristic
23
+ self.domain_heuristic = domain_heuristic
24
+
25
+ def choose(
26
+ self, choice_points: List[NDArray], shr_domains: NDArray, shr_domain_changes: NDArray, dom_indices: NDArray
27
+ ) -> None:
28
+ var_idx = self.variable_heuristic(shr_domains, dom_indices)
29
+ shr_domains_copy = shr_domains.copy(order="F")
30
+ self.domain_heuristic(shr_domains, shr_domain_changes, shr_domains_copy, dom_indices[var_idx])
31
+ choice_points.append(shr_domains_copy)
32
+
33
+
34
+ @njit("int16(int32[::1, :], uint16[:])", cache=True)
35
+ def first_not_instantiated_var_heuristic(shr_domains: NDArray, dom_indices: NDArray) -> int:
36
+ """
37
+ Chooses the first non instantiated variable.
38
+ :param shr_domains: the shared domains of the problem
39
+ :param dom_indices: the domain indices of the problem variables
40
+ :return: the index of the variable
41
+ """
42
+ for var_idx, dom_index in enumerate(dom_indices):
43
+ if shr_domains[dom_index, MIN] < shr_domains[dom_index, MAX]:
44
+ return var_idx
45
+ return -1 # cannot happen
46
+
47
+
48
+ @njit("int16(int32[::1, :], uint16[:])", cache=True)
49
+ def smallest_domain_var_heuristic(shr_domains: NDArray, dom_indices: NDArray) -> int:
50
+ """
51
+ Chooses the variable with the smallest domain and which is not instantiated.
52
+ :param shr_domains: the shared domains of the problem
53
+ :param dom_indices: the domain indices of the problem variables
54
+ :return: the index of the variable
55
+ """
56
+ min_size = sys.maxsize
57
+ min_idx = -1
58
+ for var_idx, dom_index in enumerate(dom_indices):
59
+ size = shr_domains[dom_index, MAX] - shr_domains[dom_index, MIN] # actually this is size - 1
60
+ if 0 < size < min_size:
61
+ min_idx = var_idx
62
+ min_size = size
63
+ return min_idx
64
+
65
+
66
+ @njit("(int32[::1, :], boolean[::1, :], int32[::1, :], uint16)", cache=True)
67
+ def min_value_dom_heuristic(
68
+ shr_domains: NDArray, shr_domain_changes: NDArray, shr_domains_copy: NDArray, domain_idx: int
69
+ ) -> None:
70
+ """
71
+ Chooses the first value of the domain
72
+ :param shr_domains: the shared domains of the problem
73
+ :param: shr_domain_changes: the changes to the shared domains
74
+ :param: shr_domains_copy: the shared domains to be added to the choice point
75
+ :param domain_idx: the index of the domain
76
+ """
77
+ value = shr_domains[domain_idx, MIN]
78
+ shr_domains_copy[domain_idx, MIN] = value + 1
79
+ shr_domains[domain_idx, MAX] = value
80
+ shr_domain_changes[domain_idx, MAX] = True
81
+
82
+
83
+ @njit("(int32[::1, :], boolean[::1, :], int32[::1, :], uint16)", cache=True)
84
+ def split_low_dom_heuristic(
85
+ shr_domains: NDArray, shr_domain_changes: NDArray, shr_domains_copy: NDArray, domain_idx: int
86
+ ) -> None:
87
+ """
88
+ Chooses the first half of the domain
89
+ :param shr_domains: the shared domains of the problem
90
+ :param: shr_domain_changes: the changes to the shared domains
91
+ :param: shr_domains_copy: the shared domains to be added to the choice point
92
+ :param domain_idx: the index of the domain
93
+ """
94
+ value = (shr_domains[domain_idx, MIN] + shr_domains[domain_idx, MAX]) // 2
95
+ shr_domains_copy[domain_idx, MIN] = value + 1
96
+ shr_domains[domain_idx, MAX] = value
97
+ shr_domain_changes[domain_idx, MAX] = True
@@ -0,0 +1,73 @@
1
+ from typing import List, Tuple, Union
2
+
3
+ import numpy as np
4
+ from numpy.typing import NDArray
5
+
6
+ START = 0
7
+ END = 1
8
+
9
+ MIN = 0
10
+ MAX = 1
11
+
12
+ PROP_INCONSISTENCY = 0
13
+ PROP_CONSISTENCY = 1
14
+ PROP_ENTAILMENT = 2
15
+
16
+
17
+ def new_domains_by_values(domains: List[Union[int, Tuple[int, int]]]) -> NDArray:
18
+ return np.array(
19
+ [(domain, domain) if isinstance(domain, int) else domain for domain in domains],
20
+ dtype=np.int32,
21
+ order="F",
22
+ )
23
+
24
+
25
+ def new_indices_by_values(dom_indices: List[int]) -> NDArray:
26
+ return np.array(dom_indices, dtype=np.uint16, order="C")
27
+
28
+
29
+ def new_indices(n: int) -> NDArray:
30
+ return np.empty(n, dtype=np.uint16, order="C")
31
+
32
+
33
+ def new_domain_offsets_by_values(dom_offsets: List[int]) -> NDArray:
34
+ return np.array(dom_offsets, dtype=np.int32, order="C")
35
+
36
+
37
+ def new_offsets(n: int) -> NDArray:
38
+ return np.empty(n, dtype=np.int32, order="C")
39
+
40
+
41
+ def new_data_by_values(data: List[int]) -> NDArray:
42
+ return np.array(data, dtype=np.int32, order="C")
43
+
44
+
45
+ def new_data(n: int) -> NDArray:
46
+ return np.empty(n, dtype=np.int32, order="C")
47
+
48
+
49
+ def new_domain_changes(n: int) -> NDArray:
50
+ return np.ones((n, 2), dtype=bool, order="F")
51
+
52
+
53
+ def new_triggers(n: int, init_value: bool) -> NDArray:
54
+ if init_value:
55
+ return np.ones((n, 2), dtype=bool, order="F")
56
+ else:
57
+ return np.zeros((n, 2), dtype=bool, order="F")
58
+
59
+
60
+ def new_triggered_propagators(n: int) -> NDArray:
61
+ return np.empty(n, dtype=bool, order="C")
62
+
63
+
64
+ def new_entailed_propagators(n: int) -> NDArray:
65
+ return np.zeros(n, dtype=bool, order="C")
66
+
67
+
68
+ def new_algorithms(n: int) -> NDArray:
69
+ return np.empty(n, dtype=np.int8, order="C")
70
+
71
+
72
+ def new_bounds(n: int) -> NDArray:
73
+ return np.empty((n, 2), dtype=np.uint16)
File without changes
@@ -0,0 +1,107 @@
1
+ from typing import List
2
+
3
+ from nucs.problems.problem import Problem
4
+ from nucs.propagators.propagators import ALG_AFFINE_EQ, ALG_ALLDIFFERENT
5
+
6
+ A = 0
7
+ B = 1
8
+ C = 2
9
+ D = 3
10
+ E = 4
11
+ F = 5
12
+ G = 6
13
+ H = 7
14
+ I = 8
15
+ J = 9
16
+ K = 10
17
+ L = 11
18
+ M = 12
19
+ N = 13
20
+ O = 14
21
+ P = 15
22
+ Q = 16
23
+ R = 17
24
+ S = 18
25
+ T = 19
26
+ U = 20
27
+ V = 21
28
+ W = 22
29
+ X = 23
30
+ Y = 24
31
+ Z = 25
32
+
33
+
34
+ class AlphaProblem(Problem):
35
+ """
36
+ This problem comes from the newsgroup rec.puzzle.
37
+ The numbers from 1 to 26 are assigned to the letters of the alphabet.
38
+ The numbers beside each word are the total of the values assigned to the letters in the word
39
+ (e.g for LYRE: L,Y,R,E might be to equal 5,9,20 and 13 or any other combination that add up to 47).
40
+
41
+ Find the value of each letter under the equations:
42
+ BALLET 45 GLEE 66 POLKA 59 SONG 61
43
+ CELLO 43 JAZZ 58 QUARTET 50 SOPRANO 82
44
+ CONCERT 74 LYRE 47 SAXOPHONE 134 THEME 72
45
+ FLUTE 30 OBOE 53 SCALE 51 VIOLIN 100
46
+ FUGUE 50 OPERA 65 SOLO 37 WALTZ 34
47
+ """
48
+
49
+ def __init__(self) -> None:
50
+ super().__init__(shr_domains=[(1, 26)] * 26, dom_indices=list(range(26)), dom_offsets=[0] * 26)
51
+ self.set_propagators(
52
+ [
53
+ ([A, B, E, T, L], ALG_AFFINE_EQ, [1, 1, 1, 1, 2, 45]),
54
+ ([C, E, O, L], ALG_AFFINE_EQ, [1, 1, 1, 2, 43]),
55
+ ([E, O, N, R, T, C], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 2, 74]),
56
+ ([E, F, L, U, T], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 30]),
57
+ ([E, F, G, U], ALG_AFFINE_EQ, [1, 1, 1, 2, 50]),
58
+ ([G, L, E], ALG_AFFINE_EQ, [1, 1, 2, 66]),
59
+ ([A, J, Z], ALG_AFFINE_EQ, [1, 1, 2, 58]),
60
+ ([E, L, R, Y], ALG_AFFINE_EQ, [1, 1, 1, 1, 47]),
61
+ ([E, B, O], ALG_AFFINE_EQ, [1, 1, 2, 53]),
62
+ ([A, E, P, O, R], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 65]),
63
+ ([A, K, L, O, P], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 59]),
64
+ ([A, E, Q, R, U, T], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 2, 50]),
65
+ ([A, E, H, N, P, S, X, O], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 1, 1, 2, 134]),
66
+ ([A, C, E, L, S], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 51]),
67
+ ([L, S, O], ALG_AFFINE_EQ, [1, 1, 2, 37]),
68
+ ([G, N, O, S], ALG_AFFINE_EQ, [1, 1, 1, 1, 61]),
69
+ ([A, N, P, R, S, O], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 2, 82]),
70
+ ([H, M, T, E], ALG_AFFINE_EQ, [1, 1, 1, 2, 72]),
71
+ ([L, N, O, V, I], ALG_AFFINE_EQ, [1, 1, 1, 1, 2, 100]),
72
+ ([A, L, T, W, Z], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 34]),
73
+ ([A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z], ALG_ALLDIFFERENT, []),
74
+ ]
75
+ )
76
+
77
+ def pretty_print_solution(self, solution: List[int]) -> None:
78
+ print(
79
+ {
80
+ "A": solution[A],
81
+ "B": solution[B],
82
+ "C": solution[C],
83
+ "D": solution[D],
84
+ "E": solution[E],
85
+ "F": solution[F],
86
+ "G": solution[G],
87
+ "H": solution[H],
88
+ "I": solution[I],
89
+ "J": solution[J],
90
+ "K": solution[K],
91
+ "L": solution[L],
92
+ "M": solution[M],
93
+ "N": solution[N],
94
+ "O": solution[O],
95
+ "P": solution[P],
96
+ "Q": solution[Q],
97
+ "R": solution[R],
98
+ "S": solution[S],
99
+ "T": solution[T],
100
+ "U": solution[U],
101
+ "V": solution[V],
102
+ "W": solution[W],
103
+ "X": solution[X],
104
+ "Y": solution[Y],
105
+ "Z": solution[Z],
106
+ }
107
+ )
@@ -0,0 +1,49 @@
1
+ from nucs.problems.problem import Problem
2
+ from nucs.propagators.propagators import (
3
+ ALG_EXACTLY_EQ,
4
+ ALG_LEXICOGRAPHIC_LEQ,
5
+ ALG_MIN_EQ,
6
+ )
7
+
8
+
9
+ class BIBDProblem(Problem):
10
+ """
11
+ A simple model for the BIBD problem.
12
+ See https://www.csplib.org/Problems/prob028/ for a complete description of the problem.
13
+ """
14
+
15
+ def __init__(self, v: int, b: int, r: int, k: int, l: int):
16
+ s = (v * (v - 1)) // 2
17
+ n = (v + s) * b
18
+ super().__init__(
19
+ shr_domains=[(0, 1)] * n,
20
+ dom_indices=list(range(n)),
21
+ dom_offsets=[0] * n,
22
+ )
23
+ propagators = []
24
+ # rows: counts
25
+ for i in range(0, v):
26
+ propagators.append((list(range(i * b, (i + 1) * b)), ALG_EXACTLY_EQ, [1, r]))
27
+ # columns: counts
28
+ for j in range(0, b):
29
+ propagators.append((list(range(j, v * b, b)), ALG_EXACTLY_EQ, [1, k]))
30
+ # scalar products: conjunctions and counts
31
+ conj_idx = v * b
32
+ for i1 in range(0, v - 1):
33
+ for i2 in range(i1 + 1, v):
34
+ conj_vars = []
35
+ for j in range(0, b):
36
+ propagators.append(
37
+ ([(i1 * b + j), (i2 * b + j), conj_idx], ALG_MIN_EQ, [])
38
+ ) # TODO: replace by AND ?
39
+ conj_vars.append(conj_idx)
40
+ conj_idx += 1
41
+ propagators.append((conj_vars, ALG_EXACTLY_EQ, [1, l]))
42
+ # remove symmetries
43
+ # lexleq on rows
44
+ for i in range(0, v - 1):
45
+ propagators.append((list(range(i * b, (i + 2) * b)), ALG_LEXICOGRAPHIC_LEQ, []))
46
+ # lexleq on columns
47
+ for j in range(0, b - 1):
48
+ propagators.append((list(range(j, v * b, b)) + list(range(j + 1, v * b, b)), ALG_LEXICOGRAPHIC_LEQ, []))
49
+ self.set_propagators(propagators)