
Following the same approach as when I solved the Queens game using LO, I also decided to apply what I learned in Operations Research to solve Tango, another LinkedIn minigame, as part of a strategy to increase user engagement.
How to Play Tango¶
Figure 1:Example of a Tango minigame board. Source: LinkedIn
- Objective
- Fill all the squares on the board with moons 🌙 and suns ☀️.
- Rules
- The number of moons and suns in each row and column must be the same
- There cannot be more than 2 moons or 2 suns in a row, either in a row or column
- squares separated by the
=sign must contain the same symbol - squares separated by the
×sign must contain opposite symbols
Problem Modeling¶
To formulate our LOP, it will again be necessary to define the following elements:
Ranges
Sets
Decision variables
Parameters
Objective function
Constraints
Ranges¶
- The row range, where is the total number of rows in the grid
- The column range, where is the total number of columns in the grid
Sets¶
In the case of the Tango game, in addition to the row and column ranges, it will be necessary to consider the sets of pairs of squares with = and × signs, in addition to the set of squares already filled with a sun or moon symbol. Therefore, there will be:
- Set of all board squares , which is simply the Cartesian product of the ranges and .
- Set of pairs of squares separated by
=. - Set of pairs of squares separated by
×. - Set of squares with an already filled symbol.
Decision Variables¶
As it was the case with the Queens game, the decision variables here will be binary, since Tango only uses two symbols. Because of this, the LOP is a BLOP. Thus, it was agreed that:
- , if the square in row and column will be filled with a 🌙
- , if the same square will be filled with a ☀️
Parameters¶
Parameters, unlike the decision variables, are constant values that represent fixed or known values that don’t change while the optimization process is running. In case of the Tango, there may be some cells that already come with a predefined symbol: sun or moon. As the set of parameters in our model, there will be:
- , if the square in row and column is already filled with a 🌙
- , if the same square is already filled with a ☀️
Objective Function¶
Again, as in the case of Queens, our objective is not to optimize a function, but rather to find a solution that fulfills all the rules of the game. Therefore, the Tango PPLB is not an optimization problem, but a feasibility problem. Thus, the objective function will be to maximize (or minimize) an arbitrary constant .
Constraints¶
With the previous elements well defined, we can translate the rules of the game to our BLOP as follows:
- Binarity Constraints
- First, we must define that all decision variables in our problem are binary variables, that is, they only accept 0 and 1 as the only possible values.
- Equal-Moons-Suns-Per-Row Constraints
- Since the number of suns and moons for each row must be equal, the sum of belonging to a row must equal the half of total columns, therefore 3. Since there are 6 rows, the model will have 6 of these constraints.
- Equal-Moons-Suns-Per-Column Constraints
- The same logic applies to the columns. Therefore, there are 6 more constraints.
- No-Three-Consecutive-Moons-Per-Row Constraints
- Since the 3 moons in a row cannot be next to each other, it means that the sum of three consecutive in a row must be less than or equal to 2.
- No-Three-Consecutive-Moons-Per-Column Constraints
- And the same logic applies to the columns.
- No-Three-Consecutive-Suns-Per-Row Constraints
- Similarly, since there cannot be 3 consecutive suns in a row, the sum of 3 subsequent in a row i must be greater than or equal to 1.
- No-Three-Consecutive-Suns-Per-Column Constraints
- And the same logic applies to the columns.
- Already-Filled-squares Constraints
- For each square that already has a pre-established figure, it is necessary to impose that is equal to 1 or 0, depending on whether the figure is a moon or a sun, respectively.
- Like-Pairs Constraints
- For each pair of adjacent cells that contains the
=sign between them, it is necessary to impose the constraint that the values of that pair are equal, which is the same as saying that the difference between the values of that pair must be equal to 0. - Opposite-Pairs Constraints
- Finally, for each pair of adjacent cells that contains the sign
×between them, it is necessary to impose the constraint that the values of this pair are different, which is the same as saying that the sum of the values of this pair must be equal to 1.
Abstract Model¶
Up to this point, the formulas created have been based on the premise that every Tango minigame will have 6 rows and 6 columns, which is indeed the case. However, in order to create a more generalized abstract model, we can admit that this will not always be a certainty, and therefore there is a possibility that the number of rows and columns will vary from game to game. Due to the restriction that the number of moons and suns for each row and column must be equal, it must be assumed that the total number of rows and columns are even numbers, that is, and .
Thus, having raised these points, the abstract model of the Tango minigame is formulated as follows:
Concrete Model¶
The concrete model was built based on the Tango minigame No. 151

S.t.:
- Equal-Moons-Suns-Per-Row Constraints
- (Row 1)
- (Row 2)
- (Row 3)
- (Row 4)
- (Row 5)
- (Row 6)
- Equal-Moons-Suns-Per-Column Constraints
- (Column 1)
- (Column 2)
- (Column 3)
- (Column 4)
- (Column 5)
- (Column 6)
- No-Three-Consecutive-Moons-Per-Row Constraints
- (Row 1)
- (Row 1)
- (Row 1)
- (Row 1)
- (Row 2)
- (Row 2)
- (Row 2)
- (Row 2)
- (Row 3)
- (Row 3)
- (Row 3)
- (Row 3)
- (Row 4)
- (Row 4)
- (Row 4)
- (Row 4)
- (Row 5)
- (Row 5)
- (Row 5)
- (Row 5)
- (Row 6)
- (Row 6)
- (Row 6)
- (Row 6)
- No-Three-Consecutive-Moons-Per-Column Constraints
- (Column 1)
- (Column 1)
- (Column 1)
- (Column 1)
- (Column 2)
- (Column 2)
- (Column 2)
- (Column 2)
- (Column 3)
- (Column 3)
- (Column 3)
- (Column 3)
- (Column 4)
- (Column 4)
- (Column 4)
- (Column 4)
- (Column 5)
- (Column 5)
- (Column 5)
- (Column 5)
- (Column 6)
- (Column 6)
- (Column 6)
- (Column 6)
- No-Three-Consecutive-Suns-Per-Row Constraints
- (Row 1)
- (Row 1)
- (Row 1)
- (Row 1)
- (Row 2)
- (Row 2)
- (Row 2)
- (Row 2)
- (Row 3)
- (Row 3)
- (Row 3)
- (Row 3)
- (Row 4)
- (Row 4)
- (Row 4)
- (Row 4)
- (Row 5)
- (Row 5)
- (Row 5)
- (Row 5)
- (Row 6)
- (Row 6)
- (Row 6)
- (Row 6)
- No-Three-Consecutive-Suns-Per-Column Constraints
- (Column 1)
- (Column 1)
- (Column 1)
- (Column 1)
- (Column 2)
- (Column 2)
- (Column 2)
- (Column 2)
- (Column 3)
- (Column 3)
- (Column 3)
- (Column 3)
- (Column 4)
- (Column 4)
- (Column 4)
- (Column 4)
- (Column 5)
- (Column 5)
- (Column 5)
- (Column 5)
- (Column 6)
- (Column 6)
- (Column 6)
- (Column 6)
- Like-Pairs Constraints
- Opposite-Pairs Constraints
- Already-Filled-squares Constraints
- Binarity Constraints
Solving with Pyomo¶
First of all, let’s import all the required libraries
import matplotlib.pyplot as plt
import networkx as nx
import pyomo.environ as pyoSolving Tango¶
In order to solve a Tango minigame, the solve_tango() function was created, as it follows:
def solve_tango(n:int, m:int, like_pairs:dict, opp_pairs:dict, filled_squares:dict):
model = pyo.ConcreteModel()
# Ranges
I = model.I = pyo.RangeSet(n)
J = model.J = pyo.RangeSet(m)
# Sets
H = model.squares = pyo.Set(initialize=lambda model: [(i, j) for i in I for j in J])
L = model.LikePairs = pyo.Set(initialize=like_pairs)
O = model.OppositePairs = pyo.Set(initialize=opp_pairs)
K = model.Filledsquares = pyo.Set(initialize=filled_squares.keys(), dimen=2)
# Decision variables
x = model.x = pyo.Var(I, J, within=pyo.Binary)
# Parameters
k = model.FilledValues = pyo.Param(K, initialize=filled_squares, within=pyo.Binary)
# Objective function
model.obj = pyo.Objective(expr=0, sense=pyo.maximize)
# Constraints
model.equal_moons_suns_per_row_constraints = pyo.Constraint(
I,
rule=lambda model, i: sum(x[i,j] for j in J) == m/2
)
model.equal_moons_suns_per_column_constraints = pyo.Constraint(
J,
rule=lambda model, j: sum(x[i,j] for i in I) == n/2
)
model.no_three_consecutive_moons_per_row_constraints = pyo.Constraint(
I, pyo.RangeSet(m-2),
rule=lambda model, i, j: x[i,j] + x[i,j+1] + x[i,j+2] <= 2
)
model.no_three_consecutive_suns_per_row_constraints = pyo.Constraint(
I, pyo.RangeSet(m-2),
rule=lambda model, i, j: x[i,j] + x[i,j+1] + x[i,j+2] >= 1
)
model.no_three_consecutive_moons_per_column_constraints = pyo.Constraint(
pyo.RangeSet(n-2), J,
rule=lambda model, i, j: x[i,j] + x[i+1,j] + x[i+2,j] <= 2
)
model.no_three_consecutive_suns_per_column_constraints = pyo.Constraint(
pyo.RangeSet(n-2), J,
rule=lambda model, i, j: x[i,j] + x[i+1,j] + x[i+2,j] >= 1
)
model.like_pairs_constraints = pyo.Constraint(
L,
rule=lambda model, i, j, r, s: x[i,j] - x[r,s] == 0
)
model.opposite_pairs_constraints = pyo.Constraint(
O,
rule=lambda model, i, j, r, s: x[i,j] + x[r,s] == 1
)
model.already_filled_squares_constraints = pyo.Constraint(
K,
rule=lambda model, i, j: x[i,j] == k[i,j]
)
# Solving model
solver = pyo.SolverFactory("gurobi")
result = solver.solve(model, tee=False)
# display solution
if str(result.Solver.status) == "ok":
G = nx.grid_2d_graph(n,m)
pos = {(i,j): (j, -i) for i, j in G.nodes()}
plt.figure(figsize=(3.4, 3.4))
nx.draw(
G,
pos= pos,
with_labels= True,
labels= {(i,j): int(x[i+1,j+1].value) for i, j in G.nodes()},
node_size= 1000,
node_color= ["#EEEAE7" if (i+1,j+1) in K else "white" for (i,j) in G.nodes()],
node_shape="s",
edgecolors="#EEEAE7",
linewidths= 1,
width= 0,
edgelist = [
((i-1, j-1), (r-1,s-1)) for i,j,r,s in O] + [
((i-1, j-1), (r-1,s-1)) for i,j,r,s in L
]
)
nx.draw_networkx_edge_labels(
G,
pos= pos,
edge_labels= {
((i-1, j-1), (r-1,s-1)): "×" for i,j,r,s in O} | {
((i-1, j-1), (r-1,s-1)): "=" for i,j,r,s in L
},
font_color="#887658"
)
plt.show()
else:
print('No valid solution was found!')
# dimensions of the Tango board
n = m = 6
# like (=) pairs, each element is ((i,j),(r,s))
like_pairs = [
((2, 3), (2, 4)),
((2, 1), (3, 1)),
((2, 3), (3, 3)),
((2, 6), (3, 6)),
((4, 1), (4, 2)),
((6, 3), (6, 4)),
]
# opposite (X) pairs
opp_pairs = [
((2, 4), (3, 4)),
((3, 1), (4, 1)),
((3, 3), (3, 4)),
((3, 6), (4, 6)),
((4, 5), (4, 6)),
]
# helper lists for the concrete instance (Tango #151)
# already filled squares: (i,j) -> kij
filled_squares = {
(1, 2): 1,
(1, 5): 1,
(5, 2): 0,
(5, 5): 1,
}
solve_tango(n, m, like_pairs, opp_pairs, filled_squares)
As expected, the image result matches the solution of Tango No. 151

Figure 3:Solution of Tango No. 151, March 7th, 2025. Source: LinkedIn
References¶
BELFIORE, Patrícia; FÁVERO, Luiz Paulo. Pesquisa Operacional: Para cursos de Administração, Contabilidade e Economia. Elsevier Editora Ltda., 2012.
Tango. LinkedIn. Available at https://
www .linkedin .com /games /tango/. Accessed March 7, 2025.