|
from z3 import * |
|
import json |
|
import sys |
|
|
|
|
|
|
|
categories = [ |
|
("Name", ["Bob", "Arnold", "Carol", "Alice", "Peter", "Eric"]), |
|
("Mother", ["Sarah", "Janelle", "Aniya", "Kailyn", "Holly", "Penny"]), |
|
("Children", ["Fred", "Samantha", "Bella", "Meredith", "Alice", "Timothy"]), |
|
("Vacation", ["city", "mountain", "camping", "beach", "cruise", "cultural"]), |
|
("BookGenre", ["romance", "mystery", "historical fiction", "science fiction", "biography", "fantasy"]) |
|
] |
|
|
|
|
|
NUM_POSITIONS = len(categories[0][1]) |
|
|
|
item_to_cat_and_index = {} |
|
for cat_idx, (cat_str, item_list) in enumerate(categories): |
|
for item_idx, item_str in enumerate(item_list): |
|
item_to_cat_and_index[(cat_str, item_str)] = (cat_idx, item_idx) |
|
|
|
Vars = [] |
|
for cat_idx, (cat_name, item_list) in enumerate(categories): |
|
var = IntVector(cat_name, len(item_list)) |
|
Vars.append(var) |
|
|
|
s = Solver() |
|
|
|
for cat_idx, (cat_name, item_list) in enumerate(categories): |
|
for item_idx, item_str in enumerate(item_list): |
|
s.add(Vars[cat_idx][item_idx] >= 1, Vars[cat_idx][item_idx] <= NUM_POSITIONS) |
|
s.add(Distinct(Vars[cat_idx])) |
|
|
|
def pos(cat_str, item_str): |
|
(cat_idx, item_idx) = item_to_cat_and_index[(cat_str, item_str)] |
|
return Vars[cat_idx][item_idx] |
|
|
|
|
|
|
|
s.add(pos("Vacation", "beach") != 2) |
|
|
|
|
|
s.add(pos("BookGenre", "fantasy") < pos("Name", "Peter")) |
|
|
|
|
|
s.add(pos("Mother", "Sarah") == pos("Vacation", "city")) |
|
|
|
|
|
s.add(pos("Vacation", "camping") > pos("Name", "Peter")) |
|
|
|
|
|
s.add(pos("Vacation", "cruise") == pos("Children", "Meredith")) |
|
|
|
|
|
s.add(Abs(pos("Mother", "Timothy") - pos("Name", "Eric")) == 2) |
|
|
|
|
|
s.add(pos("Mother", "Janelle") != 2) |
|
|
|
|
|
s.add(pos("Children", "Fred") < pos("Name", "Eric")) |
|
|
|
|
|
s.add(pos("Vacation", "cultural") == 4) |
|
|
|
|
|
s.add(pos("Mother", "Janelle") != 1) |
|
|
|
|
|
s.add(pos("Mother", "Holly") > pos("BookGenre", "historical fiction")) |
|
|
|
|
|
s.add(pos("Children", "Bella") < pos("Name", "Alice")) |
|
|
|
|
|
s.add(pos("Name", "Arnold") > pos("BookGenre", "fantasy")) |
|
|
|
|
|
s.add(pos("BookGenre", "mystery") == 4) |
|
|
|
|
|
s.add(pos("Children", "Alice") == pos("Vacation", "camping")) |
|
|
|
|
|
s.add(pos("Mother", "Kailyn") == pos("Vacation", "cruise")) |
|
|
|
|
|
s.add(Abs(pos("BookGenre", "fantasy") - pos("Mother", "Aniya")) == 3) |
|
|
|
|
|
s.add(pos("BookGenre", "fantasy") == pos("Name", "Carol")) |
|
|
|
|
|
s.add(pos("Vacation", "cruise") == pos("BookGenre", "biography")) |
|
|
|
|
|
s.add(pos("BookGenre", "fantasy") == 3) |
|
|
|
|
|
s.add(pos("Mother", "Aniya") == pos("BookGenre", "romance")) |
|
|
|
|
|
s.add(pos("Mother", "Janelle") != 4) |
|
|
|
|
|
s.add(pos("Children", "Fred") != 4) |
|
|
|
|
|
s.add(pos("BookGenre", "biography") != 2) |
|
|
|
|
|
s.add(Abs(pos("Mother", "Holly") - pos("Name", "Eric")) == 3) |
|
|
|
|
|
if s.check() == sat: |
|
m = s.model() |
|
rows = [] |
|
header = ["House"] + [cat_name for cat_name, _ in categories] |
|
for position in range(1, NUM_POSITIONS + 1): |
|
row = [str(position)] |
|
for cat_idx, (cat_name, item_list) in enumerate(categories): |
|
for item_idx, item_str in enumerate(item_list): |
|
if m.evaluate(Vars[cat_idx][item_idx]).as_long() == position: |
|
row.append(item_str) |
|
break |
|
rows.append(row) |
|
result_dict = {"header": header, "rows": rows} |
|
|
|
cnt = 1 |
|
block = [] |
|
for cat_idx, (cat_name, item_list) in enumerate(categories): |
|
for i in range(NUM_POSITIONS): |
|
block.append(Vars[cat_idx][i] != m[Vars[cat_idx][i]]) |
|
s.add(Or(block)) |
|
while s.check() == sat: |
|
m = s.model() |
|
cnt += 1 |
|
block = [] |
|
for cat_idx, (cat_name, item_list) in enumerate(categories): |
|
for i in range(NUM_POSITIONS): |
|
block.append(Vars[cat_idx][i] != m[Vars[cat_idx][i]]) |
|
s.add(Or(block)) |
|
print(f"sat:{cnt}") |
|
else: |
|
print(f"error") |