Last Tango with Math (CP)

Last Tango with Math (CP)

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:

  • There is a board which should be filled with sun (1) and moon (0).
  • Some Cells should have different values (cross)
  • Some Cells should have similar values (=)
  • The number of suns and stars in each row and column should be the same
  • The value of some specific cells are already known (as shown in the picture)

Contraint programming by Alireza Soroudi

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.

  • Step zero: is to create a simple visualisation to know what is known and what is unknown.

  • Let's make it more informative and inject the known values into it ( i know this is not star but matplotlib does not have a marker with 'moon' shape, sorry about it)


  • The first step is to decide what kind of variables and constraints should be used. The obvious answer is boolean variables (to determine 0/1 value of unknown cells).
  • Step 2: we need to create the constraints according to the problem requirements:

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)        

  • For every three consecutive cells they should not have the same value
  • to address this requirement, all 3 consecutive cells (horizontally and verticall) are first found and then the rules are applied to them


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])
                ]        

  • Rules

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)        

  • Some cells should have the same values (keep them in a list)

for (n,m) in same:
  model.Add(U[n] == U[m])        

  • Some cells should have the different values (keep them in a list)

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


Fatemeh Afsharnia, Ph.D.

Postdoctoral Researcher, Reliability and Maintenance Engineering

1 个月

Great??

Hakan Kjellerstrand

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

要查看或添加评论,请登录

Alireza Soroudi, PhD的更多文章

  • How large is your snake? A CP approach

    How large is your snake? A CP approach

    I am not sure if it's important or not but sometimes you are curious to know how many items you can fit into your…

    14 条评论
  • Gerrymandering using Constraint Programming

    Gerrymandering using Constraint Programming

    As the U.S.

    11 条评论
  • From Solving to Designing Queen Problem using CP

    From Solving to Designing Queen Problem using CP

    In the last thrilling episode of this newsletter, we cracked the LinkedIn Queen Problem! ?? But then it hit me—how does…

    22 条评论
  • How to Cut your Board using CP?

    How to Cut your Board using CP?

    Cutting the shapes has always fascinated mathematicians. In this episode of Optimization in Open Source, we focus on…

    13 条评论
  • Queens game using CP

    Queens game using CP

    This is an exciting installment of our newsletter! I recently came across a fascinating challenge on LinkedIn that…

    20 条评论
  • How Machine Learning can Help Power System Operators ?

    How Machine Learning can Help Power System Operators ?

    Machine Learning has become a buzzword in recent times. Recruiters often label positions as "data scientist" roles…

    10 条评论
  • Optimization in Action: The Train of a Single Color

    Optimization in Action: The Train of a Single Color

    Let's explain the routing wavelength assignment (RWA) problem. The general objective of the RWA problem is to maximize…

    6 条评论
  • Optimal Data-Driven Strategies for Efficient Demining Operations

    Optimal Data-Driven Strategies for Efficient Demining Operations

    Demining involves removing landmines to ensure safety. In military contexts, the goal is to quickly clear paths using…

    6 条评论
  • Solving Large Scale TSP using OR

    Solving Large Scale TSP using OR

    The Traveling Salesman Problem (TSP) might seem tedious initially, but tackling it on a large scale is like embarking…

    12 条评论
  • Optimal Marriage Using OR

    Optimal Marriage Using OR

    While an analytical mind might employ optimization algorithms to find the perfect match, true love often dances to its…

    37 条评论

社区洞察

其他会员也浏览了