
How to Play Queens¶
Figure 1:Example of a Queens minigame board. Source: LinkedIn Queens
- Objective
- To place a crown in each row, column, and colored region on the board.
- Rules
- There can only be one crown in each row, column and colored region;
- There cannot be adjacent crowns, not even along adjacent diagonals.
Problem Modeling¶
Before solving Queens, it is necessary to translate the game elements into the following components of the LOP:
Ranges
Sets
Decision Variables
Objective Function
Constraints
Ranges¶
Defining the ranges is a fundamental step for the proper definition of the other components of the LOP. For the case of Queens, three ranges will be considered:
- Range of rows, where is the total number of rows on the board (in this case, = 7)
- Range of columns, where is the total number of columns on the board (also = 7 for this case)
- Range of colored regions in game, where is the total number of regions on the board ( = 7)
Sets¶
By defining the ranges and , let’s define three sets for solving the Queens game:
- Set of all squares on the board, which is nothing more than the Cartesian product of the ranges and
- Set of colored regions and says to which region a square belongs.
- Set of all pairs of diagonally adjacent squares. This set will be useful so to make defining the constraints easier later on.
Decision variables¶
The decision variables will be binary variables , which will assume only two values:
- , if the crown is located in row and column ;
- , otherwise.
Objective function¶
Since we don’t have an objective function to maximize or minimize, we are not actually dealing with an optimization problem, but rather a feasibility problem, i.e., our objective is only to find a feasible solution that meets all the game’s constraints. Because of this, we can define the objective function as minimizing (or maximizing, it doesn’t matter) an arbitrary constant. Thus, the objective function will not depend on the decision variables, so that the model doesn’t seek to optimize it and only worries about meeting the constraints.
Constraints¶
With the previous elements well defined, we can finally translate Queens’ rules into constraints for our BLOP model. Let’s go step by step:
- Binarity Constraints
- The first constraint we need to define right away is that all decision variables in our problem are binary variables, meaning they only accept 0 and 1 as valid values.
- Single-Crown-Per-Row Constraints
- Since each row on the board must have only one crown, the sum of all belonging to a row must equal 1. As there are 7 rows in total, there will be 7 such constraints, one for each row.
- Single-Crown-Per-Column Constraints
- The same logic applies to the columns. Since there are 7 columns on the board, there will be 7 more constraints, one for each column.
- Single-Crown-Per-Region Constraints
- The same logic also applies to the colored regions. For each region of the board, the sum of the belonging to a region must be equal to 1. Since there are 7 regions, there will be 7 more constraints.
- Diagonally-Adjacent-squares Constraints
- Finally, we must not forget the rule that there cannot be adjacent crowns, not even along the diagonals. The cases of vertical and horizontal proximity do not need to be addressed, since the row and column constraints already cover this. Therefore, we only need to worry about imposing constraints for the two diagonal directions in each pair of shared-vertex squares. With the set well defined, this constraint is easily defined as it follows.
Abstract Model¶
With all components defined, it is possible to model the game of Queens using the following abstract model.
Concrete Model¶
In this article, let’s apply LO techniques to solve the Queens No. 307, which will be an instance of the abstract model presented earlier, that is, its concrete model.

Figure 2:Queens No. 307, March 3rd, 2025. Source: LinkedIn Queens
The concrete model for the game above will be the following:
S.t.:
- Single-Crown-Per-Row Constraints
- (Row 1)
- (Row 2)
- (Row 3)
- (Row 4)
- (Row 5)
- (Row 6)
- (Row 7)
- Single-Crown-Per-Column Constraints
- (Column 1)
- (Column 2)
- (Column 3)
- (Column 4)
- (Column 5)
- (Column 6)
- (Column 7)
- Single-Crown-Per-Region Constraints
- (Purple Region)
- (Orange Region)
- (Blue Region)
- (Green Region)
- (Gray Region)
- (Red Region)
- (Yellow Region)
- Principal Diagonals Constraints
- Secondary Diagonals Constraints
- Binarity Constraints
Solving Queens¶
In order to solve the presented game, the linkedin-games library counts on Queens class, which implements the Queens game and its constraints, as well as methods to solve it and visualize the game’s solution.
So, first of all, let’s import the Queens class and create an instance of it, passing its size and its colored regions as a dictionary of color: {squares} items, as shown bellow:
from linkedin_games import Queens
# Queens No. 307
regions = {
"#BBA3E1": { # Purple
(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (2,6),
(2,7), (3,6), (3,7), (4,6), (4,7), (5,7), (6,7), (7,7)
},
"#FFC794": { # Orange
(2,1), (2,2), (2,3), (2,4), (3,1), (4,1), (4,2),
(5,1), (5,2), (6,1), (6,2), (6,4), (6,5), (6,6),
(7,1), (7,2), (7,3), (7,4), (7,5), (7,6)
},
"#94BEFF": {(2,5), (3,5)}, # Blue
"#B3DF9E": {(3,2), (3,3)}, # Green
"#E0E0E0": {(3,4), (4,3), (4,4), (4,5), (5,4)}, # Gray
"#FF7B61": {(5,3), (6,3)}, # Red
"#E6F388": {(5,5), (5,6)} # Yellow
}
queens = Queens(7, regions)The method solve() class a modeler to implement the Linear Optimization logic of the Queens game before solving it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49import pyomo.environ as pyo from .._shared.optimization.modeler.opt_modeler import OptModeler from ._game_grid import QueensGrid class QueensOptModeler(OptModeler[QueensGrid]): def _set_range_sets(self) -> None: super()._set_range_sets() self._model.K = pyo.Set(initialize=self._game.regions.keys()) # Colored Regions def _set_composite_sets(self) -> None: super()._set_composite_sets() self._model.R = pyo.Set( # Region Squares self._model.K, initialize=self._game.regions, dimen=2, domain=self._model.S ) self._model.D = pyo.Set( # Diagonals initialize=lambda model: [((i, j), (i + 1, j + 1)) for (i, j) in model.S if (i + 1, j + 1) in model.S] + [((i, j), (i + 1, j - 1)) for (i, j) in model.S if (i + 1, j - 1) in model.S] ) def _set_parameters(self) -> None: super()._set_parameters() def _set_decision_variables(self) -> None: self._model.x = pyo.Var(self._model.S, domain=pyo.Binary, initialize=0) def _set_constraints(self) -> None: self._model.single_crown_per_row_constraints = pyo.Constraint( self._model.I, rule=lambda model, i: pyo.quicksum(model.x[i, j] for j in model.J) == 1 ) self._model.single_crown_per_column_constraints = pyo.Constraint( self._model.J, rule=lambda model, j: pyo.quicksum(model.x[i, j] for i in model.I) == 1 ) self._model.single_crown_per_region_constraints = pyo.Constraint( self._model.K, rule=lambda model, k: pyo.quicksum(model.x[i, j] for (i, j) in model.R[k]) == 1 ) self._model.adjacent_squares_by_vertex_constraints = pyo.Constraint( self._model.D, rule=lambda model, i, j, r, s: model.x[i, j] + model.x[r, s] <= 1 )
Program 1:Creating the model with Pyomo components.
The method display(), in its turn, calls a renderer to show the Queens board with the crowned squares marked on it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40import matplotlib.pyplot as plt import networkx as nx from .._shared.visualization.renderer.renderer import GameRenderer from ._game_grid import QueensGrid class QueensRenderer(GameRenderer[QueensGrid]): def _set_grid(self) -> None: super()._set_grid() nx.set_node_attributes( # Adding a color for each square on the grid self._grid, name="color", values={ (i-1, j-1): color_code for color_code, squares in self._game.regions.items() for (i, j) in squares } ) def display(self) -> None: plt.figure(figsize=(self._width, self._height)) nx.draw( self._grid, pos={(i, j): (j, -i) for i, j in self._grid.nodes()}, with_labels=True, arrows=False, labels={ (i-1, j-1): "" if not value else "O" if value == 1 else "" for (i, j), value in self._game.squares.items() }, node_size=1100, node_color=list(nx.get_node_attributes(self._grid, "color").values()), node_shape="s", # Squared-shape nodes width=0, edgecolors="black", linewidths=.5 ) plt.show()
Program 2:The Queens’ renderer
So to solve the game and display its results, just call the public methods solve() and display().
queens.solve().display()
The output board matches the solution of the Queens No. 307, as expected.

Figure 3:Solution of Queens No. 307, March 3rd, 2025. Source: LinkedIn Queens