Last Tango with Math (CP)
Alireza Soroudi, PhD
Lead Data Scientist @ bluecrux || SMIEEE || Optimization expert in Supply chain management|| Healthcare management || Lab Digitalization || Power and Energy systems || Developer || Author / Speaker || (views are mine)
The Last Tango is no longer in Paris and it seems to be on Linkedin. After coming across a logic puzzle on LinkedIn, I decided to, as some might say, take the fun out of it by solving it using constraint programming (hopefully it fills you with another type of fun) . Voilà, here is the latest episode of Optimization Online .
Here is the description of the puzzle:
How should we solve the problem?
Disclaimer: We're not addressing any particularly useful, meaningful, or world-changing problem here. So if you're looking for that, this may not be suitable for you. We assume you already know how to make transition from toy problems to realistic ones.
For each row/column the number of suns = number of stars = 3
for r in range(6):
model.Add(sum([U[c] for c in nodes if cell[c][0] == r]) == 3)
model.Add(sum([U[c] for c in nodes if cell[c][1] == r]) == 3)
all_verticals = [(n,m,p) for n in nodes for m in nodes for p in nodes
if (cell[n][0]== cell[m][0] and cell[m][0]== cell[p][0]) and
(cell[n][1]+1 == cell[m][1] and cell[m][1]+1== cell[p][1])
]
all_horizonss = [(n,m,p) for n in nodes for m in nodes for p in nodes
if (cell[n][1]== cell[m][1] and cell[m][1]== cell[p][1]) and
(cell[n][0]+1 == cell[m][0] and cell[m][0]+1== cell[p][0])
]
for (n,m,p) in all_verticals:
model.Add(U[n] + U[m] + U[p] <= 2)
model.Add(U[n].Not() + U[m].Not() + U[p].Not() <= 2)
for (n,m,p) in all_horizonss:
model.Add(U[n] + U[m] + U[p] <= 2)
model.Add(U[n].Not() + U[m].Not() + U[p].Not() <= 2)
for (n,m) in same:
model.Add(U[n] == U[m])
for (n,m) in dif:
model.Add(U[n] != U[m])
The whole model is here :
model = cp_model.CpModel()
solver = cp_model.CpSolver()
U = {c:model.NewBoolVar(f"sunorstar_{c}") for c in nodes}
for n in nodes:
if cell[n][2] == 1:
model.Add(U[n] == 1)
elif cell[n][2] == 0:
model.Add(U[n] == 0)
for r in range(6):
model.Add(sum([U[c] for c in nodes if cell[c][0] == r]) == 3)
model.Add(sum([U[c] for c in nodes if cell[c][1] == r]) == 3)
all_verticals = [(n,m,p) for n in nodes for m in nodes for p in nodes
if (cell[n][0]== cell[m][0] and cell[m][0]== cell[p][0]) and
(cell[n][1]+1 == cell[m][1] and cell[m][1]+1== cell[p][1])
]
all_horizonss = [(n,m,p) for n in nodes for m in nodes for p in nodes
if (cell[n][1]== cell[m][1] and cell[m][1]== cell[p][1]) and
(cell[n][0]+1 == cell[m][0] and cell[m][0]+1== cell[p][0])
]
for (n,m,p) in all_verticals:
model.Add(U[n] + U[m] + U[p] <= 2)
model.Add(U[n].Not() + U[m].Not() + U[p].Not() <= 2)
for (n,m,p) in all_horizonss:
model.Add(U[n] + U[m] + U[p] <= 2)
model.Add(U[n].Not() + U[m].Not() + U[p].Not() <= 2)
for (n,m) in same:
model.Add(U[n] == U[m])
for (n,m) in dif:
model.Add(U[n] != U[m])
status = solver.Solve(model)
Results:
All rules are satisfied and all cell values are identified.
Feel free to join Optimization Online news letter.
The full code is available on github repo
Postdoctoral Researcher, Reliability and Maintenance Engineering
1 个月Great??
Software developer (retired) / Independent researcher
1 个月Fun puzzle and a nice model. The problem resembles some other grid puzzles, e.g. Binoxxo, Binairo, etc, but the addition of the special signs is unique. Would you mind linking to the specific file in the GitHub repo? By the way, here's my Picat solution: https://hakank.org/picat/tango.pi