NUCS 4.3.0__tar.gz → 4.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nucs-4.3.0 → nucs-4.4/NUCS.egg-info}/PKG-INFO +1 -1
- {nucs-4.3.0/NUCS.egg-info → nucs-4.4}/PKG-INFO +1 -1
- {nucs-4.3.0 → nucs-4.4}/docs/source/conf.py +2 -2
- {nucs-4.3.0 → nucs-4.4}/nucs/constants.py +3 -3
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/bibd/__main__.py +1 -1
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/golomb/__main__.py +4 -4
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/knapsack/__main__.py +2 -2
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/magic_sequence/__main__.py +1 -1
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/schur_lemma/__main__.py +1 -1
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/tsp/__main__.py +4 -2
- nucs-4.4/nucs/examples/tsp/tsp_problem.py +47 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/solvers/backtrack_solver.py +11 -11
- {nucs-4.3.0 → nucs-4.4}/pyproject.toml +1 -1
- {nucs-4.3.0 → nucs-4.4}/tests/examples/test_bibd.py +3 -3
- {nucs-4.3.0 → nucs-4.4}/tests/examples/test_golomb.py +1 -1
- {nucs-4.3.0 → nucs-4.4}/tests/examples/test_magic_sequence.py +1 -1
- {nucs-4.3.0 → nucs-4.4}/tests/examples/test_tsp.py +2 -4
- {nucs-4.3.0 → nucs-4.4}/tests/solvers/test_backtrack_solver.py +10 -10
- {nucs-4.3.0 → nucs-4.4}/tests/solvers/test_multiprocessing_solver.py +13 -13
- nucs-4.3.0/nucs/examples/tsp/tsp_problem.py +0 -53
- {nucs-4.3.0 → nucs-4.4}/LICENSE.md +0 -0
- {nucs-4.3.0 → nucs-4.4}/NUCS.egg-info/SOURCES.txt +0 -0
- {nucs-4.3.0 → nucs-4.4}/NUCS.egg-info/dependency_links.txt +0 -0
- {nucs-4.3.0 → nucs-4.4}/NUCS.egg-info/requires.txt +0 -0
- {nucs-4.3.0 → nucs-4.4}/NUCS.egg-info/top_level.txt +0 -0
- {nucs-4.3.0 → nucs-4.4}/README.md +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/alpha/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/alpha/__main__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/alpha/alpha_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/bibd/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/bibd/bibd_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/donald/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/donald/__main__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/donald/donald_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/golomb/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/golomb/golomb_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/knapsack/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/knapsack/knapsack_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/magic_sequence/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/magic_sequence/magic_sequence_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/magic_square/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/magic_square/__main__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/magic_square/magic_square_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/quasigroup/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/quasigroup/__main__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/quasigroup/quasigroup_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/queens/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/queens/__main__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/queens/queens_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/schur_lemma/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/schur_lemma/schur_lemma_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/sports_tournament_scheduling/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/sports_tournament_scheduling/__main__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/sports_tournament_scheduling/sports_tournament_scheduling_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/sudoku/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/sudoku/sudoku_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/tsp/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/tsp/total_cost_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/tsp/tsp_instances.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/examples/tsp/tsp_var_heuristic.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/heuristics/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/heuristics/first_not_instantiated_var_heuristic.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/heuristics/greatest_domain_var_heuristic.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/heuristics/heuristics.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/heuristics/max_regret_var_heuristic.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/heuristics/max_value_dom_heuristic.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/heuristics/mid_value_dom_heuristic.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/heuristics/min_cost_dom_heuristic.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/heuristics/min_value_dom_heuristic.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/heuristics/smallest_domain_var_heuristic.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/heuristics/split_high_dom_heuristic.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/heuristics/split_low_dom_heuristic.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/heuristics/value_dom_heuristic.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/numba_helper.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/numpy_helper.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/problems/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/problems/circuit_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/problems/latin_square_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/problems/permutation_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/problems/problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/affine_eq_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/affine_geq_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/affine_leq_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/alldifferent_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/and_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/count_eq_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/dummy_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/element_iv_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/element_lic_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/element_liv_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/exactly_eq_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/exactly_true_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/gcc_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/lexicographic_leq_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/max_eq_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/max_leq_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/min_eq_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/min_geq_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/no_sub_cycle_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/permutation_aux_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/propagators.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/relation_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/propagators/scc_propagator.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/solvers/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/solvers/bound_consistency_algorithm.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/solvers/choice_points.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/solvers/consistency_algorithms.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/solvers/multiprocessing_solver.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/solvers/shaving_consistency_algorithm.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/nucs/solvers/solver.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/setup.cfg +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/examples/test_alpha.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/examples/test_donald.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/examples/test_knapsack.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/examples/test_latin_square.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/examples/test_magic_square.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/examples/test_quasigroup.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/examples/test_queens.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/examples/test_schur_lemma.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/examples/test_sports_tournament_scheduling.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/examples/test_sudokus.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/heuristics/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/heuristics/test_max_value_dom_heuristic.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/heuristics/test_mid_value_dom_heuristic.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/heuristics/test_min_value_dom_heuristic.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/problems/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/problems/test_circuit_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/problems/test_permutation_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/problems/test_problem.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/__init__.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_affine_eq.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_affine_geq.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_affine_leq.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_alldifferent.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_count_eq.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_element_iv.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_element_lic.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_element_liv.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_exactly_eq.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_gcc.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_lexicographic_leq.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_max_eq.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_max_leq.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_min_eq.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_min_geq.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_no_sub_cycle.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_relation.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/propagators/test_scc.py +0 -0
- {nucs-4.3.0 → nucs-4.4}/tests/solvers/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: NUCS
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.4
|
|
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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: NUCS
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.4
|
|
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
|
|
@@ -14,9 +14,9 @@ import os
|
|
|
14
14
|
|
|
15
15
|
from numba import bool, int32, int64, types, uint8, uint16 # type: ignore
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
OPTIM_RESET = "RESET"
|
|
18
|
+
OPTIM_PRUNE = "PRUNE"
|
|
19
|
+
OPTIM_MODES = [OPTIM_RESET, OPTIM_PRUNE]
|
|
20
20
|
|
|
21
21
|
RG_START = 0 # index corresponding the start of a values range
|
|
22
22
|
RG_END = 1 # index corresponding the end of a values range
|
|
@@ -33,7 +33,7 @@ if __name__ == "__main__":
|
|
|
33
33
|
args = parser.parse_args()
|
|
34
34
|
problem = BIBDProblem(args.v, args.b, args.r, args.k, args.l, args.symmetry_breaking)
|
|
35
35
|
solver = BacktrackSolver(
|
|
36
|
-
problem, dom_heuristic_idx=DOM_HEURISTIC_MAX_VALUE, log_level=args.log_level,
|
|
36
|
+
problem, dom_heuristic_idx=DOM_HEURISTIC_MAX_VALUE, log_level=args.log_level, stacks_max_height=128
|
|
37
37
|
)
|
|
38
38
|
solver.solve_all()
|
|
39
39
|
print(solver.get_statistics())
|
|
@@ -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, OPTIM_MODES, OPTIM_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
|
|
@@ -26,7 +26,7 @@ if __name__ == "__main__":
|
|
|
26
26
|
parser = argparse.ArgumentParser()
|
|
27
27
|
parser.add_argument("-n", type=int, default=10)
|
|
28
28
|
parser.add_argument("--log_level", choices=LOG_LEVELS, default=LOG_LEVEL_INFO)
|
|
29
|
-
parser.add_argument("--opt_mode", choices=
|
|
29
|
+
parser.add_argument("--opt_mode", choices=OPTIM_MODES, default=OPTIM_PRUNE)
|
|
30
30
|
parser.add_argument("--processors", type=int, default=1)
|
|
31
31
|
parser.add_argument("--symmetry_breaking", action=argparse.BooleanOptionalAction, default=True)
|
|
32
32
|
args = parser.parse_args()
|
|
@@ -36,14 +36,14 @@ if __name__ == "__main__":
|
|
|
36
36
|
MultiprocessingSolver(
|
|
37
37
|
[
|
|
38
38
|
BacktrackSolver(
|
|
39
|
-
prob, consistency_alg_idx=consistency_alg_golomb, log_level=args.log_level,
|
|
39
|
+
prob, consistency_alg_idx=consistency_alg_golomb, log_level=args.log_level, stacks_max_height=128
|
|
40
40
|
)
|
|
41
41
|
for prob in problem.split(args.processors, 0)
|
|
42
42
|
]
|
|
43
43
|
)
|
|
44
44
|
if args.processors > 1
|
|
45
45
|
else BacktrackSolver(
|
|
46
|
-
problem, consistency_alg_idx=consistency_alg_golomb, log_level=args.log_level,
|
|
46
|
+
problem, consistency_alg_idx=consistency_alg_golomb, log_level=args.log_level, stacks_max_height=128
|
|
47
47
|
)
|
|
48
48
|
)
|
|
49
49
|
solution = solver.minimize(problem.length_idx, mode=args.opt_mode)
|
|
@@ -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, OPTIM_MODES, OPTIM_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,7 +24,7 @@ from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
|
24
24
|
if __name__ == "__main__":
|
|
25
25
|
parser = argparse.ArgumentParser()
|
|
26
26
|
parser.add_argument("--log_level", choices=LOG_LEVELS, default=LOG_LEVEL_INFO)
|
|
27
|
-
parser.add_argument("--opt_mode", choices=
|
|
27
|
+
parser.add_argument("--opt_mode", choices=OPTIM_MODES, default=OPTIM_RESET)
|
|
28
28
|
args = parser.parse_args()
|
|
29
29
|
problem = KnapsackProblem(
|
|
30
30
|
[40, 40, 38, 38, 36, 36, 34, 34, 32, 32, 30, 30, 28, 28, 26, 26, 24, 24, 22, 22],
|
|
@@ -33,7 +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
|
-
|
|
36
|
+
stacks_max_height=128,
|
|
37
37
|
)
|
|
38
38
|
solver.solve_all()
|
|
39
39
|
print(solver.get_statistics())
|
|
@@ -27,6 +27,6 @@ if __name__ == "__main__":
|
|
|
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, stacks_max_height=128)
|
|
31
31
|
solver.solve_all()
|
|
32
32
|
print(solver.get_statistics())
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
###############################################################################
|
|
13
13
|
import argparse
|
|
14
14
|
|
|
15
|
-
from
|
|
15
|
+
from rich import print
|
|
16
|
+
|
|
17
|
+
from nucs.constants import LOG_LEVEL_INFO, LOG_LEVELS, OPTIM_MODES, OPTIM_PRUNE
|
|
16
18
|
from nucs.examples.tsp.tsp_instances import TSP_INSTANCES
|
|
17
19
|
from nucs.examples.tsp.tsp_problem import TSPProblem
|
|
18
20
|
from nucs.examples.tsp.tsp_var_heuristic import tsp_var_heuristic
|
|
@@ -27,7 +29,7 @@ if __name__ == "__main__":
|
|
|
27
29
|
parser = argparse.ArgumentParser()
|
|
28
30
|
parser.add_argument("--log_level", choices=LOG_LEVELS, default=LOG_LEVEL_INFO)
|
|
29
31
|
parser.add_argument("--name", choices=["GR17", "GR21", "GR24"], default="GR17")
|
|
30
|
-
parser.add_argument("--opt_mode", choices=
|
|
32
|
+
parser.add_argument("--opt_mode", choices=OPTIM_MODES, default=OPTIM_PRUNE)
|
|
31
33
|
parser.add_argument("--processors", type=int, default=1)
|
|
32
34
|
parser.add_argument("--shaving", type=bool, action=argparse.BooleanOptionalAction, default=False)
|
|
33
35
|
args = parser.parse_args()
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
# __ _ _____ _____
|
|
3
|
+
# | \ | | / ____| / ____|
|
|
4
|
+
# | \| | _ _ | | | (___
|
|
5
|
+
# | . ` | | | | | | | \___ \
|
|
6
|
+
# | |\ | | |_| | | |____ ____) |
|
|
7
|
+
# |_| \_| \__,_| \_____| |_____/
|
|
8
|
+
#
|
|
9
|
+
# Fast constraint solving in Python - https://github.com/yangeorget/nucs
|
|
10
|
+
#
|
|
11
|
+
# Copyright 2024 - Yan Georget
|
|
12
|
+
###############################################################################
|
|
13
|
+
from typing import List
|
|
14
|
+
|
|
15
|
+
from nucs.problems.circuit_problem import CircuitProblem
|
|
16
|
+
from nucs.propagators.propagators import ALG_AFFINE_EQ, ALG_ELEMENT_IV
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TSPProblem(CircuitProblem):
|
|
20
|
+
""" """
|
|
21
|
+
|
|
22
|
+
def __init__(self, costs: List[List[int]]) -> None:
|
|
23
|
+
"""
|
|
24
|
+
Inits the problem.
|
|
25
|
+
:param costs: the costs between vertices as a list of lists of integers
|
|
26
|
+
"""
|
|
27
|
+
n = len(costs)
|
|
28
|
+
super().__init__(n)
|
|
29
|
+
max_costs = [max(cost_row) for cost_row in costs]
|
|
30
|
+
min_costs = [min([cost for cost in cost_row if cost > 0]) for cost_row in costs]
|
|
31
|
+
self.succ_costs = self.add_variables([(min_costs[i], max_costs[i]) for i in range(n)])
|
|
32
|
+
self.pred_costs = self.add_variables([(min_costs[i], max_costs[i]) for i in range(n)])
|
|
33
|
+
self.total_cost = self.add_variable((sum(min_costs), sum(max_costs))) # the total cost
|
|
34
|
+
self.add_propagators([([i, self.succ_costs + i], ALG_ELEMENT_IV, costs[i]) for i in range(n)])
|
|
35
|
+
self.add_propagators([([n + i, self.pred_costs + i], ALG_ELEMENT_IV, costs[i]) for i in range(n)])
|
|
36
|
+
self.add_propagator(
|
|
37
|
+
(list(range(self.succ_costs, self.succ_costs + n)) + [self.total_cost], ALG_AFFINE_EQ, [1] * n + [-1, 0])
|
|
38
|
+
)
|
|
39
|
+
self.add_propagator(
|
|
40
|
+
(list(range(self.pred_costs, self.pred_costs + n)) + [self.total_cost], ALG_AFFINE_EQ, [1] * n + [-1, 0])
|
|
41
|
+
)
|
|
42
|
+
# total_cost_prop_idx = register_propagator(
|
|
43
|
+
# get_triggers_total_cost, get_complexity_total_cost, compute_domains_total_cost
|
|
44
|
+
# )
|
|
45
|
+
# costs = [cost for cost_row in costs for cost in cost_row]
|
|
46
|
+
# self.add_propagator((list(range(n)) + [self.total_cost], total_cost_prop_idx, costs))
|
|
47
|
+
# self.add_propagator((list(range(n, 2 * n)) + [self.total_cost], total_cost_prop_idx, costs))
|
|
@@ -23,7 +23,7 @@ from nucs.constants import (
|
|
|
23
23
|
MAX,
|
|
24
24
|
MIN,
|
|
25
25
|
NUMBA_DISABLE_JIT,
|
|
26
|
-
|
|
26
|
+
OPTIM_RESET,
|
|
27
27
|
PROBLEM_BOUND,
|
|
28
28
|
PROBLEM_UNBOUND,
|
|
29
29
|
SIGNATURE_COMPUTE_DOMAINS,
|
|
@@ -91,7 +91,7 @@ class BacktrackSolver(Solver):
|
|
|
91
91
|
var_heuristic_params: List[List[int]] = [[]],
|
|
92
92
|
dom_heuristic_idx: int = DOM_HEURISTIC_MIN_VALUE,
|
|
93
93
|
dom_heuristic_params: List[List[int]] = [[]],
|
|
94
|
-
|
|
94
|
+
stacks_max_height: int = 64,
|
|
95
95
|
log_level: str = LOG_LEVEL_INFO,
|
|
96
96
|
):
|
|
97
97
|
"""
|
|
@@ -105,7 +105,7 @@ class BacktrackSolver(Solver):
|
|
|
105
105
|
:param dom_heuristic_idx: the index of the heuristic for reducing a domain
|
|
106
106
|
:param dom_heuristic_params: a list of lists of parameters,
|
|
107
107
|
usually parameters are costs and there is a list of value costs per variable/shared domain
|
|
108
|
-
:param
|
|
108
|
+
:param stacks_max_height: the maximal height of the choice point stacks
|
|
109
109
|
:param log_level: the log level as a string
|
|
110
110
|
"""
|
|
111
111
|
super().__init__(problem, log_level)
|
|
@@ -122,11 +122,11 @@ class BacktrackSolver(Solver):
|
|
|
122
122
|
self.consistency_alg_idx = consistency_alg_idx
|
|
123
123
|
self.triggered_propagators = np.ones(problem.propagator_nb, dtype=np.bool)
|
|
124
124
|
logger.debug("Initializing choice points")
|
|
125
|
-
self.shr_domains_stack = np.empty((
|
|
126
|
-
self.not_entailed_propagators_stack = np.empty((
|
|
127
|
-
self.dom_update_stack = np.empty((
|
|
125
|
+
self.shr_domains_stack = np.empty((stacks_max_height, self.problem.shr_domain_nb, 2), dtype=np.int32)
|
|
126
|
+
self.not_entailed_propagators_stack = np.empty((stacks_max_height, self.problem.propagator_nb), dtype=np.bool)
|
|
127
|
+
self.dom_update_stack = np.empty((stacks_max_height, 2), dtype=np.uint16)
|
|
128
128
|
self.stacks_top = np.ones((1,), dtype=np.uint8)
|
|
129
|
-
logger.info(f"
|
|
129
|
+
logger.info(f"The stacks of the choice points have a maximal height of {stacks_max_height}")
|
|
130
130
|
cp_init(
|
|
131
131
|
self.shr_domains_stack,
|
|
132
132
|
self.not_entailed_propagators_stack,
|
|
@@ -157,7 +157,7 @@ class BacktrackSolver(Solver):
|
|
|
157
157
|
STATS_LBL_SOLVER_SOLUTION_NB: int(self.statistics[STATS_IDX_SOLVER_SOLUTION_NB]),
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
def minimize(self, variable_idx: int, mode: str =
|
|
160
|
+
def minimize(self, variable_idx: int, mode: str = OPTIM_RESET) -> Optional[NDArray]:
|
|
161
161
|
"""
|
|
162
162
|
Return the solution that minimizes a variable.
|
|
163
163
|
:param variable_idx: the index of the variable to minimize
|
|
@@ -167,7 +167,7 @@ class BacktrackSolver(Solver):
|
|
|
167
167
|
logger.info(f"Minimizing (mode {mode}) variable {variable_idx} (domain {domain}))")
|
|
168
168
|
return self.optimize(variable_idx, MAX, mode)
|
|
169
169
|
|
|
170
|
-
def maximize(self, variable_idx: int, mode: str =
|
|
170
|
+
def maximize(self, variable_idx: int, mode: str = OPTIM_RESET) -> Optional[NDArray]:
|
|
171
171
|
"""
|
|
172
172
|
Return the solution that maximizes a variable.
|
|
173
173
|
:param variable_idx: the index of the variable to maximize
|
|
@@ -218,7 +218,7 @@ class BacktrackSolver(Solver):
|
|
|
218
218
|
) is not None:
|
|
219
219
|
logger.info(f"Found a local optimum: {solution[variable_idx]}")
|
|
220
220
|
best_solution = solution
|
|
221
|
-
if mode ==
|
|
221
|
+
if mode == OPTIM_RESET:
|
|
222
222
|
logger.debug("Resetting solver")
|
|
223
223
|
cp_init(
|
|
224
224
|
self.shr_domains_stack,
|
|
@@ -373,7 +373,7 @@ class BacktrackSolver(Solver):
|
|
|
373
373
|
break
|
|
374
374
|
logger.info(f"Found a local optimum: {solution[variable_idx]}")
|
|
375
375
|
solution_queue.put((processor_idx, solution, None))
|
|
376
|
-
if mode ==
|
|
376
|
+
if mode == OPTIM_RESET:
|
|
377
377
|
logger.debug("Resetting solver")
|
|
378
378
|
cp_init(
|
|
379
379
|
self.shr_domains_stack,
|
|
@@ -18,18 +18,18 @@ from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
|
18
18
|
class TestBIBD:
|
|
19
19
|
def test_6_10_5_3_2(self) -> None:
|
|
20
20
|
problem = BIBDProblem(6, 10, 5, 3, 2)
|
|
21
|
-
solver = BacktrackSolver(problem,
|
|
21
|
+
solver = BacktrackSolver(problem, stacks_max_height=128)
|
|
22
22
|
solver.solve_all()
|
|
23
23
|
assert solver.statistics[STATS_IDX_SOLVER_SOLUTION_NB] == 1
|
|
24
24
|
|
|
25
25
|
def test_7_7_3_3_1(self) -> None:
|
|
26
26
|
problem = BIBDProblem(7, 7, 3, 3, 1)
|
|
27
|
-
solver = BacktrackSolver(problem,
|
|
27
|
+
solver = BacktrackSolver(problem, stacks_max_height=128)
|
|
28
28
|
solver.solve_all()
|
|
29
29
|
assert solver.statistics[STATS_IDX_SOLVER_SOLUTION_NB] == 1
|
|
30
30
|
|
|
31
31
|
def test_8_14_7_4_3(self) -> None:
|
|
32
32
|
problem = BIBDProblem(8, 14, 7, 4, 3)
|
|
33
|
-
solver = BacktrackSolver(problem,
|
|
33
|
+
solver = BacktrackSolver(problem, stacks_max_height=128)
|
|
34
34
|
solver.solve_all()
|
|
35
35
|
assert solver.statistics[STATS_IDX_SOLVER_SOLUTION_NB] == 92
|
|
@@ -29,7 +29,7 @@ class TestGolomb:
|
|
|
29
29
|
def test_golomb(self, mark_nb: int, length: int) -> None:
|
|
30
30
|
problem = GolombProblem(mark_nb)
|
|
31
31
|
consistency_alg_golomb = register_consistency_algorithm(golomb_consistency_algorithm)
|
|
32
|
-
solver = BacktrackSolver(problem, consistency_alg_idx=consistency_alg_golomb,
|
|
32
|
+
solver = BacktrackSolver(problem, consistency_alg_idx=consistency_alg_golomb, stacks_max_height=128)
|
|
33
33
|
solution = solver.minimize(problem.length_idx)
|
|
34
34
|
assert solution is not None
|
|
35
35
|
assert solution[problem.length_idx] == length
|
|
@@ -28,7 +28,7 @@ class TestMagicSequence:
|
|
|
28
28
|
decision_domains=list(range(size - 1, -1, -1)),
|
|
29
29
|
var_heuristic_idx=VAR_HEURISTIC_FIRST_NOT_INSTANTIATED,
|
|
30
30
|
dom_heuristic_idx=DOM_HEURISTIC_MIN_VALUE,
|
|
31
|
-
|
|
31
|
+
stacks_max_height=128,
|
|
32
32
|
)
|
|
33
33
|
solutions = solver.find_all()
|
|
34
34
|
assert solver.statistics[STATS_IDX_SOLVER_SOLUTION_NB] == 1
|
|
@@ -12,13 +12,12 @@
|
|
|
12
12
|
###############################################################################
|
|
13
13
|
import pytest
|
|
14
14
|
|
|
15
|
-
from nucs.constants import STATS_IDX_SOLVER_SOLUTION_NB
|
|
15
|
+
from nucs.constants import OPTIM_PRUNE, STATS_IDX_SOLVER_SOLUTION_NB
|
|
16
16
|
from nucs.examples.tsp.tsp_instances import TSP_INSTANCES
|
|
17
17
|
from nucs.examples.tsp.tsp_problem import TSPProblem
|
|
18
18
|
from nucs.examples.tsp.tsp_var_heuristic import tsp_var_heuristic
|
|
19
19
|
from nucs.heuristics.heuristics import DOM_HEURISTIC_MIN_COST, register_var_heuristic
|
|
20
20
|
from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
21
|
-
from nucs.solvers.consistency_algorithms import CONSISTENCY_ALG_SHAVING
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
class TestTSP:
|
|
@@ -47,13 +46,12 @@ class TestTSP:
|
|
|
47
46
|
costs = tsp_instance + tsp_instance
|
|
48
47
|
solver = BacktrackSolver(
|
|
49
48
|
problem,
|
|
50
|
-
consistency_alg_idx=CONSISTENCY_ALG_SHAVING,
|
|
51
49
|
decision_domains=list(range(0, 2 * n)),
|
|
52
50
|
var_heuristic_idx=tsp_var_heuristic_idx,
|
|
53
51
|
var_heuristic_params=costs,
|
|
54
52
|
dom_heuristic_idx=DOM_HEURISTIC_MIN_COST,
|
|
55
53
|
dom_heuristic_params=costs,
|
|
56
54
|
)
|
|
57
|
-
solution = solver.minimize(problem.total_cost)
|
|
55
|
+
solution = solver.minimize(problem.total_cost, mode=OPTIM_PRUNE)
|
|
58
56
|
assert solution is not None
|
|
59
57
|
assert solution[problem.total_cost] == minimum
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
###############################################################################
|
|
13
13
|
import pytest
|
|
14
14
|
|
|
15
|
-
from nucs.constants import
|
|
15
|
+
from nucs.constants import OPTIM_PRUNE, OPTIM_RESET, STATS_LBL_SOLVER_CHOICE_DEPTH, STATS_LBL_SOLVER_SOLUTION_NB
|
|
16
16
|
from nucs.heuristics.heuristics import (
|
|
17
17
|
DOM_HEURISTIC_MID_VALUE,
|
|
18
18
|
DOM_HEURISTIC_MIN_VALUE,
|
|
@@ -86,19 +86,19 @@ class TestBacktrackSolver:
|
|
|
86
86
|
@pytest.mark.parametrize(
|
|
87
87
|
"mode,dom_heuristic, solution_nb",
|
|
88
88
|
[
|
|
89
|
-
(
|
|
90
|
-
(
|
|
91
|
-
(
|
|
92
|
-
(
|
|
93
|
-
(
|
|
94
|
-
(
|
|
95
|
-
(
|
|
96
|
-
(
|
|
89
|
+
(OPTIM_PRUNE, DOM_HEURISTIC_MIN_VALUE, 5),
|
|
90
|
+
(OPTIM_PRUNE, DOM_HEURISTIC_MID_VALUE, 3),
|
|
91
|
+
(OPTIM_PRUNE, DOM_HEURISTIC_SPLIT_LOW, 5),
|
|
92
|
+
(OPTIM_PRUNE, DOM_HEURISTIC_SPLIT_HIGH, 1),
|
|
93
|
+
(OPTIM_RESET, DOM_HEURISTIC_MIN_VALUE, 5),
|
|
94
|
+
(OPTIM_RESET, DOM_HEURISTIC_MID_VALUE, 3),
|
|
95
|
+
(OPTIM_RESET, DOM_HEURISTIC_SPLIT_LOW, 5),
|
|
96
|
+
(OPTIM_RESET, DOM_HEURISTIC_SPLIT_HIGH, 1),
|
|
97
97
|
],
|
|
98
98
|
)
|
|
99
99
|
def test_maximize(self, mode: str, dom_heuristic: int, solution_nb: int) -> None:
|
|
100
100
|
problem = Problem([(1, 5)])
|
|
101
|
-
solver = BacktrackSolver(problem, dom_heuristic_idx=dom_heuristic,
|
|
101
|
+
solver = BacktrackSolver(problem, dom_heuristic_idx=dom_heuristic, stacks_max_height=8)
|
|
102
102
|
solution = solver.maximize(0, mode=mode)
|
|
103
103
|
assert solution is not None
|
|
104
104
|
assert solution.tolist() == [5]
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
###############################################################################
|
|
13
13
|
import pytest
|
|
14
14
|
|
|
15
|
-
from nucs.constants import
|
|
15
|
+
from nucs.constants import OPTIM_PRUNE, OPTIM_RESET, STATS_LBL_SOLVER_SOLUTION_NB
|
|
16
16
|
from nucs.problems.problem import Problem
|
|
17
17
|
from nucs.propagators.propagators import ALG_ALLDIFFERENT, ALG_RELATION
|
|
18
18
|
from nucs.solvers.backtrack_solver import BacktrackSolver
|
|
@@ -40,18 +40,18 @@ class TestMultiprocessingSolver:
|
|
|
40
40
|
@pytest.mark.parametrize(
|
|
41
41
|
"mode, split_var, split_nb, solution_nb",
|
|
42
42
|
[
|
|
43
|
-
(
|
|
44
|
-
(
|
|
45
|
-
(
|
|
46
|
-
(
|
|
47
|
-
(
|
|
48
|
-
(
|
|
49
|
-
(
|
|
50
|
-
(
|
|
51
|
-
(
|
|
52
|
-
(
|
|
53
|
-
(
|
|
54
|
-
(
|
|
43
|
+
(OPTIM_PRUNE, 0, 1, 6),
|
|
44
|
+
(OPTIM_RESET, 0, 1, 6),
|
|
45
|
+
(OPTIM_PRUNE, 0, 2, 6),
|
|
46
|
+
(OPTIM_RESET, 0, 2, 6),
|
|
47
|
+
(OPTIM_PRUNE, 0, 3, 6),
|
|
48
|
+
(OPTIM_RESET, 0, 3, 6),
|
|
49
|
+
(OPTIM_PRUNE, 1, 1, 6),
|
|
50
|
+
(OPTIM_RESET, 1, 1, 6),
|
|
51
|
+
(OPTIM_PRUNE, 1, 2, 6),
|
|
52
|
+
(OPTIM_RESET, 1, 2, 6),
|
|
53
|
+
(OPTIM_PRUNE, 1, 3, 6),
|
|
54
|
+
(OPTIM_RESET, 1, 3, 6),
|
|
55
55
|
],
|
|
56
56
|
)
|
|
57
57
|
def test_minimize_relation(self, mode: str, split_var: int, split_nb: int, solution_nb: int) -> None:
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
###############################################################################
|
|
2
|
-
# __ _ _____ _____
|
|
3
|
-
# | \ | | / ____| / ____|
|
|
4
|
-
# | \| | _ _ | | | (___
|
|
5
|
-
# | . ` | | | | | | | \___ \
|
|
6
|
-
# | |\ | | |_| | | |____ ____) |
|
|
7
|
-
# |_| \_| \__,_| \_____| |_____/
|
|
8
|
-
#
|
|
9
|
-
# Fast constraint solving in Python - https://github.com/yangeorget/nucs
|
|
10
|
-
#
|
|
11
|
-
# Copyright 2024 - Yan Georget
|
|
12
|
-
###############################################################################
|
|
13
|
-
from typing import List
|
|
14
|
-
|
|
15
|
-
from nucs.examples.tsp.total_cost_propagator import (
|
|
16
|
-
compute_domains_total_cost,
|
|
17
|
-
get_complexity_total_cost,
|
|
18
|
-
get_triggers_total_cost,
|
|
19
|
-
)
|
|
20
|
-
from nucs.problems.circuit_problem import CircuitProblem
|
|
21
|
-
from nucs.propagators.propagators import ALG_AFFINE_EQ, ALG_ELEMENT_IV, register_propagator
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class TSPProblem(CircuitProblem):
|
|
25
|
-
""" """
|
|
26
|
-
|
|
27
|
-
def __init__(self, cost_rows: List[List[int]]) -> None:
|
|
28
|
-
"""
|
|
29
|
-
Inits the problem.
|
|
30
|
-
:param cost_rows: the costs between vertices
|
|
31
|
-
"""
|
|
32
|
-
n = len(cost_rows)
|
|
33
|
-
super().__init__(n)
|
|
34
|
-
max_costs = [max(cost_row) for cost_row in cost_rows]
|
|
35
|
-
min_costs = [min([cost for cost in cost_row if cost > 0]) for cost_row in cost_rows]
|
|
36
|
-
self.next_costs = self.add_variables([(min_costs[i], max_costs[i]) for i in range(n)])
|
|
37
|
-
self.prev_costs = self.add_variables([(min_costs[i], max_costs[i]) for i in range(n)])
|
|
38
|
-
self.total_cost = self.add_variable((sum(min_costs), sum(max_costs))) # the total cost
|
|
39
|
-
for i in range(n):
|
|
40
|
-
self.add_propagator(([i, self.next_costs + i], ALG_ELEMENT_IV, cost_rows[i]))
|
|
41
|
-
self.add_propagator(([n + i, self.prev_costs + i], ALG_ELEMENT_IV, cost_rows[i]))
|
|
42
|
-
self.add_propagator(
|
|
43
|
-
(list(range(self.next_costs, self.next_costs + n)) + [self.total_cost], ALG_AFFINE_EQ, [1] * n + [-1, 0])
|
|
44
|
-
)
|
|
45
|
-
self.add_propagator(
|
|
46
|
-
(list(range(self.prev_costs, self.prev_costs + n)) + [self.total_cost], ALG_AFFINE_EQ, [1] * n + [-1, 0])
|
|
47
|
-
)
|
|
48
|
-
total_cost_prop_idx = register_propagator(
|
|
49
|
-
get_triggers_total_cost, get_complexity_total_cost, compute_domains_total_cost
|
|
50
|
-
)
|
|
51
|
-
costs = [cost for cost_row in cost_rows for cost in cost_row]
|
|
52
|
-
self.add_propagator((list(range(n)) + [self.total_cost], total_cost_prop_idx, costs))
|
|
53
|
-
self.add_propagator((list(range(n, 2 * n)) + [self.total_cost], total_cost_prop_idx, costs))
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|