-
Notifications
You must be signed in to change notification settings - Fork 76
Expand file tree
/
Copy pathtest_parser.py
More file actions
158 lines (146 loc) · 6.64 KB
/
Copy pathtest_parser.py
File metadata and controls
158 lines (146 loc) · 6.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
from constraint import (
compile_to_constraints,
parse_restrictions,
Constraint,
FunctionConstraint,
CompilableFunctionConstraint,
ExactSumConstraint,
MinSumConstraint,
MaxSumConstraint,
ExactProdConstraint,
MinProdConstraint,
MaxProdConstraint,
VariableExactSumConstraint,
VariableExactProdConstraint,
VariableMinProdConstraint,
VariableMaxProdConstraint,
)
from collections.abc import Iterable
def test_parse_restrictions():
domains = {"x": [50, 100], "y": [0, 1]}
constraints = ["x != 320", "y == 0 or x % 32 != 0", "50 <= x * y < 100"]
# test the conversion to constraints
parsed_multi_constraints = parse_restrictions(constraints, domains)
assert isinstance(parsed_multi_constraints, list) and isinstance(parsed_multi_constraints[0], tuple)
assert len(parsed_multi_constraints) == 4
parsed, params = parsed_multi_constraints[0]
assert isinstance(parsed, str)
assert params == ["x"]
parsed, params = parsed_multi_constraints[1]
assert isinstance(parsed, str)
assert all(param in domains for param in params)
parsed, params = parsed_multi_constraints[2]
assert isinstance(parsed, MinProdConstraint)
assert all(param in domains for param in params)
parsed, params = parsed_multi_constraints[3]
assert isinstance(parsed, MaxProdConstraint)
assert all(param in domains for param in params)
# test the conversion to constraints with a real-world edge-case
rw_domains = dict()
rw_domains["x"] = [1, 2, 3, 4, 5, 6, 7, 8]
rw_domains["y"] = [1, 2, 3, 4, 5, 6, 7, 8]
parsed_constraint, params_constraint = parse_restrictions(["x*y<30"], rw_domains)[0]
assert all(param in rw_domains for param in params_constraint)
assert isinstance(parsed_constraint, MaxProdConstraint)
assert 29 < parsed_constraint._maxprod < 30
parsed_constraint, params_constraint = parse_restrictions(["30<x*y"], rw_domains)[0]
assert all(param in rw_domains for param in params_constraint)
assert isinstance(parsed_constraint, MinProdConstraint)
assert 30 < parsed_constraint._minprod < 31
def test_compile_to_constraints():
domains = {"x": [50, 100], "y": [0, 1]}
constraints = [
"x != 320", # FunctionConstraint
"y == 0 or x % 32 != 0",# FunctionConstraint
"x == 100", # ExactSumConstraint
"100 == x + y", # ExactSumConstraint
"x == 100+y", # FunctionConstraint
"x == x+y", # VariableExactSumConstraint
"51 <= x+y", # MinSumConstraint
"50 < x+y", # MinSumConstraint
"100-y >= x", # MaxSumConstraint
"100 == x-y", # FunctionConstraint
"x / y == 100", # FunctionConstraint
"x / y == x", # VariableExactProdConstraint
"x / y <= x", # VariableMinProdConstraint
"x / y >= x", # VariableMaxProdConstraint
"50 <= x * y < 100", # becomes splitted MinProdConstraint and MaxProdConstraint
]
expected_constraint_types = [
FunctionConstraint,
FunctionConstraint,
ExactSumConstraint,
ExactSumConstraint,
FunctionConstraint, # TODO should be VariableExactSumConstraint after Roadmap point 1 is implemented
VariableExactSumConstraint,
MinSumConstraint,
MinSumConstraint,
MaxSumConstraint, # with rewriting "100-y >= x" becomes "100 >= x+y"
FunctionConstraint, # TODO should be VariableExactSumConstraint after Roadmap point 1 is implemented # with rewriting "100 == x-y" becomes "100+y == x"
FunctionConstraint, # TODO should be VariableExactSumConstraint after Roadmap point 1 is implemented # with rewriting "x / y == 100" becomes "x==100 * y"
VariableExactProdConstraint,
VariableMinProdConstraint,
VariableMaxProdConstraint,
MinProdConstraint,
MaxProdConstraint,
]
compiled = compile_to_constraints(constraints, domains, picklable=False)
# assert len(compiled) == len(expected_constraint_types)
for r, vals, r_str in compiled:
assert isinstance(r, Constraint)
assert isinstance(vals, Iterable) and all(isinstance(v, str) for v in vals)
if isinstance(r, (FunctionConstraint, CompilableFunctionConstraint)):
assert isinstance(r_str, str)
else:
assert r_str is None
# check whether the expected types match (may have to be adjusted to be order independent in future)
for i, (r, _, cons) in enumerate(compiled):
expected = expected_constraint_types[i]
assert isinstance(r, expected), f"Expected {expected} but got {type(r)} for constraint {constraints[i]}" # the constraint lookup is correct until there are split restrictions
if callable(expected):
assert callable(r)
def test_compile_to_constraints_picklable():
domains = {"x": [50, 100], "y": [0, 1]}
constraints = [
"x != 320",
"y == 0 or x % 32 != 0",
"50 <= x * y < 100"
]
expected_constraint_types = [
CompilableFunctionConstraint,
CompilableFunctionConstraint,
MinProdConstraint,
MaxProdConstraint
]
compiled = compile_to_constraints(constraints, domains, picklable=True)
assert len(compiled) == len(expected_constraint_types)
for r, vals, r_str in compiled:
assert isinstance(r, Constraint)
assert isinstance(vals, Iterable) and all(isinstance(v, str) for v in vals)
if isinstance(r, (FunctionConstraint, CompilableFunctionConstraint)):
assert isinstance(r_str, str)
else:
assert r_str is None
# check whether the expected types match (may have to be adjusted to be order independent in future)
for i, (r, _, _) in enumerate(compiled):
expected = expected_constraint_types[i]
if callable(expected):
assert callable(r)
else:
assert isinstance(r, expected)
def test_compile_non_numeric():
domains = {"x": ["a2", "b4", "c6"], "y": [True, False]}
constraints = [
"x == 'a'",
"y == 'd' or x != 'b'",
"'a' <= x + y < 'c'"
]
compiled = compile_to_constraints(constraints, domains, picklable=False)
assert len(compiled) == 4
for r, vals, r_str in compiled:
assert isinstance(r, (Constraint, CompilableFunctionConstraint))
assert isinstance(vals, Iterable) and all(isinstance(v, str) for v in vals)
if isinstance(r, (FunctionConstraint, CompilableFunctionConstraint)):
assert isinstance(r_str, str)
else:
assert r_str is None