Skip to content

Commit ac1ea56

Browse files
committed
Fix the checking of solutions containing MiniZinc defined enums
1 parent 931b6b5 commit ac1ea56

File tree

4 files changed

+29
-11
lines changed

4 files changed

+29
-11
lines changed

CHANGELOG.rst

+4
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,17 @@ Changed
2222
^^^^^^^
2323
- The MiniZinc Python repository moved from GitLab to GitHub, replacing GitLab
2424
CI for GitHub Actions for the continuous testing.
25+
- Values of an enumerated type defined in MiniZinc will now appear in solutions
26+
as a member of a singular anonymous ``enum.Enum`` class.
2527

2628
Fixed
2729
^^^^^
2830
- Handle the cancellation of asynchronous solving and correctly dispose of the
2931
process
3032
- Correct the JSON representation of sets of with ``IntEnum`` members. (Lists
3133
are still not correctly represented).
34+
- ``check_solution`` will now correctly handle solution values of an enumerated
35+
type defined in MiniZinc.
3236

3337
0.4.0_ - 2020-10-06
3438
------------

src/minizinc/json.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ def __init__(self, enum_map=None, *args, **kwargs):
2424
self.enum_map = enum_map
2525
JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)
2626

27+
def _lookup_enum(self, name: str):
28+
if name in self.enum_map:
29+
return self.enum_map[name]
30+
else:
31+
# TODO: mypy seems to believe name the elements should be literals,
32+
# but I cannot find this anywhere in the documentation
33+
anon_enum = Enum("AnonymousEnum", name) # type: ignore
34+
self.enum_map[name] = anon_enum(1)
35+
return anon_enum(1)
36+
2737
def object_hook(self, obj):
2838
if len(obj) == 1 and "set" in obj:
2939
if len(obj["set"]) == 1 and isinstance(obj["set"][0], list):
@@ -36,11 +46,11 @@ def object_hook(self, obj):
3646
assert len(item) == 2
3747
li.extend([i for i in range(item[0], item[1] + 1)])
3848
elif len(obj) == 1 and "e" in obj:
39-
li.append(self.enum_map.get(obj["e"], obj["e"]))
49+
li.append(self._lookup_enum(obj["e"]))
4050
else:
4151
li.append(item)
4252
return set(li)
4353
elif len(obj) == 1 and "e" in obj:
44-
return self.enum_map.get(obj["e"], obj["e"])
54+
return self._lookup_enum(obj["e"])
4555
else:
4656
return obj

tests/test_helpers.py

+5
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,8 @@ def test_dict(self):
4242
assert check_solution(
4343
self.instance, {"x": [5, 6]}, Status.SATISFIED, self.other_solver
4444
)
45+
46+
def test_enum(self):
47+
self.instance.add_string("""enum Foo = {A, B};var Foo: f;""")
48+
result = self.instance.solve()
49+
assert check_result(self.instance, result, self.other_solver)

tests/test_types.py

+8-9
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ class TestEnum(InstanceTestCase):
1717
def test_value(self):
1818
self.instance.add_string("constraint d == Mo;")
1919
result = self.instance.solve()
20-
assert isinstance(result["d"], str)
21-
assert result["d"] == "Mo"
20+
assert isinstance(result["d"], enum.Enum)
21+
assert result["d"].name == "Mo"
2222

2323
def test_cmp_in_instance(self):
2424
self.instance.add_string("var DAY: d2;")
2525
self.instance.add_string("constraint d < d2;")
2626
result = self.instance.solve()
27-
assert isinstance(result["d"], str)
28-
assert isinstance(result["d2"], str)
27+
assert isinstance(result["d"], enum.Enum)
28+
assert isinstance(result["d2"], enum.Enum)
2929
# TODO: assert result["d"] < result["d2"]
3030

3131
def test_cmp_between_instances(self):
@@ -36,9 +36,9 @@ def test_cmp_between_instances(self):
3636
inst = Instance(self.solver)
3737
inst.add_string(self.code + append)
3838
result2 = inst.solve()
39-
assert isinstance(result["d"], str)
40-
assert isinstance(result2["d"], str)
41-
assert result["d"] == result2["d"]
39+
assert isinstance(result["d"], enum.Enum)
40+
assert isinstance(result2["d"], enum.Enum)
41+
assert result["d"].name == result2["d"].name
4242

4343
inst = Instance(self.solver)
4444
inst.add_string(
@@ -49,8 +49,7 @@ def test_cmp_between_instances(self):
4949
+ append
5050
)
5151
result2 = inst.solve()
52-
# TODO: assert type(result["d"]) != type(result2["d"])
53-
# TODO: assert result["d"] == result2["d"]
52+
assert result["d"].name == result2["d"].name
5453

5554
def test_assign(self):
5655
self.instance = Instance(self.solver)

0 commit comments

Comments
 (0)