# N-Queens

In the N-queen problem, $N$ queens must be placed on an $N\times N$ chessboard without interfering with each other. There can never be more than one queen on a chess row, column or diagonal because of the queen's ability to move vertically, horizontally and diagonally.

## Solution Representation

A naive representation is to use a binary matrix to represent a chessboard $c_{ij}$ where $c_{ij}=1$ would indicate a queen in row $i$ and column $j$; however the search space cardinality (number of solutions) is huge for this representation. A permutation-based representation can be used instead. A permutation will contain in position $j$ the row $i$ where a queen is, removing a lot of infeasible solutions (queens attacking horizontally and vertically).

Let's compute the number of solutions (a.k.a. cardinality):

`julia> using Metaheuristics`

`julia> N = 8 # for 8-queens`

`8`

`julia> cardinality(BitArraySpace(N*N))`

`18446744073709551616`

`julia> cardinality(PermutationSpace(N))`

`40320`

## Objective Function

It is necessary to minimize the number of attacks, the following objective function is proposed to this end:

```
function attacks(chessboard)
N = length(chessboard)
n_attacks = 0
# check attack in both diagonas for each queen
for i = 1:N
Δrows = i + chessboard[i]
Δcols = i - chessboard[i]
for j = (i+1):N
# check diagonal [\]
n_attacks += j + chessboard[j] == Δrows ? 1 : 0
# check inverse diagonal [/]
n_attacks += j - chessboard[j] == Δcols ? 1 : 0
end
end
2n_attacks
end
```

`attacks (generic function with 1 method)`

It can observed that horizontal and vertical are not considered due to the adopted solution representation.

## Let's find a solution

To minimize the number of attacks, let's use a Genetic Algorithm:

```
N = 8
result = optimize(attacks, PermutationSpace(N), GA)
```

Optimization Result =================== Iteration: 20 Minimum: 0 Minimizer: [5, 7, 1, …, 3] Function calls: 2000 Total time: 0.0053 s Stop reason: Due to Convergence Termination criterion.

It can be observed that the number of attacks is:

`n_attacks = minimum(result)`

`0.0`

The optimal permutation is:

`perm = minimizer(result)`

```
8-element Vector{Int64}:
5
7
1
4
2
8
6
3
```

Corresponding chessboard configuration:

```
chessboard = zeros(Bool, N, N)
for (i,j) = enumerate(perm); chessboard[i,j] = true;end
chessboard
```

```
8×8 Matrix{Bool}:
0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0
0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 1 0 0
0 0 1 0 0 0 0 0
```

## The 20-queens case

```
N = 20
perm = optimize(attacks, PermutationSpace(N), GA, seed=1) |> minimizer
```

```
20-element Vector{Int64}:
7
4
13
8
18
5
15
19
1
3
14
9
2
12
20
17
11
6
10
16
```

`attacks(perm)`

`0`

```
chessboard = zeros(Bool, N, N)
for (i,j) = enumerate(perm); chessboard[i,j] = true;end
chessboard
```

```
20×20 Matrix{Bool}:
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
```