  Projet Centrale
  Puzzle
  Tony WU

# Préliminaires

## Objectifs

Le problème est le suivant. Une image a été découpée en morceaux rectangulaires **plus ou moins** de mêmes dimensions et ces morceaux ont ensuite été changé de place. L'objectif est de créer un algorithme qui prendrait le puzzle en entrée et renverrait l'image d'origine.

**On peut décomposer le problème en plusieurs parties :**

1) Récupérer les pièces de puzzle.

2) FORCE BRUTE: On va essayer toutes les permutations possibles de pièces, au nombre de $(n_{lignes} \times n_{colonnes})!$
  - En fait, comme ce nombre est trop important, on va, lors de la construction de l'image finale, ne garder que les configurations qui présentent en faible gradient sur les bords. Pour définir la notion de faible gradient, on va se dire arbitrairement que si le gradient calculé est dans l'intervalle ±5% du gradient moyen calculé sur les bords de l'image d'origine, alors on rejette la solution actuelle et on passe à la suivante.

4) On crée une sorte de fonction coût, disons par exemple, pour une image en niveaux de gris :
\begin{equation}
J = \sum_{\text{bords des pièces}} (\vec{\nabla{u}} \circ \vec{n})^2
\end{equation}

Ainsi, l'objectif sera de trouver la configuration de puzzle qui minimise $J$.

## Modules

```python
import numpy as np
from PIL import Image
from PIL import ImageFilter
import matplotlib.pyplot as plt
import matplotlib.patches as patches

import os
import time

from pprint import pprint

from copy import deepcopy

from itertools import permutations

from IPython.display import clear_output
import ipywidgets as widgets
from ipywidgets import interact, interact_manual

import sys
sys.setrecursionlimit(1000)

import pdb
```

```python
%load_ext autoreload
%autoreload 2
```

    The autoreload extension is already loaded. To reload it, use:
      %reload_ext autoreload

```python
from utils import *
```

# Découpage de l'image

**Rappel important**
Avec PIL, le système de coordonées pris est le suivant :

```python
# Global variables, to change according to the given puzzle!
filename = 'img_test.jpg'
nb_lines = 9
nb_cols = 9

im_shuffled = read_img(filename)

cropped = split_img(im_shuffled, nb_lines, nb_cols, margin=(25,35))

plt.imshow(cropped[(0,0)])
```

```python
save_cropped(cropped)
```

    Images successfully saved.

# Calcul des gradients au bord

## Calcul du gradient

On essaie de garder les couleurs pour la configuration finale donc on somme le gradient pour chaque canal de couleur.

```python
im1 = cropped[(0,0)]
im2 = cropped[(1,0)]
```

```python
grad_x(im1, im2)
```

    43446

```python
grad_y(im1, im2)
```

    54450

```python
mean_grad(cropped, nb_lines, nb_cols)
```

    3681387.0

## Assemblage du puzzle

```python
im_test = read_cropped_im(0, 0)
plt.imshow(im_test)
```

```python
map_config = next(get_current_permutations(cropped))
original_img = config_to_img(map_config, nb_lines, nb_cols)

display_cropped(cropped, nb_lines, nb_cols, figsize=(5,6))
```

Nous allons essayer d'implémenter un algorithme fondé sur le backtracking.
Le score est choisi comme étant une moyenne du gradient selon x et selon y, mis au carré et divisé par le nombre de pièces.

L'objectif de la mise au carré est de pénaliser plus sévèrement les gros delta de gradient.

# Partie ajoutée pour Martin

*Décrire la méthode utilisée*

```python
dicBestConfig = getBestConfig(cropped, nb_lines, nb_cols)
```

```python
pprint(dicBestConfig)
```

    {(0, 0): {'E': (8, 7),
              'N': (1, 2),
              'S': (6, 5),
              'W': (1, 2),
              'grad_E': 37557,
              'grad_N': 16542,
              'grad_S': 24015,
              'grad_W': 15123},
     (0, 1): {'E': (0, 5),
              'N': (6, 7),
              'S': (0, 3),
              'W': (8, 5),
              'grad_E': 52467,
              'grad_N': 35199,
              'grad_S': 38364,
              'grad_W': 51903},
     (0, 2): {'E': (7, 6),
              'N': (7, 2),
              'S': (0, 0),
              'W': (0, 3),
              'grad_E': 52557,
              'grad_N': 36384,
              'grad_S': 34899,
              'grad_W': 50661},
     (0, 3): {'E': (6, 5),
              'N': (7, 6),
              'S': (7, 4),
              'W': (6, 5),
              'grad_E': 34935,
              'grad_N': 25797,
              'grad_S': 30480,
              'grad_W': 45003},
     (0, 4): {'E': (1, 5),
              'N': (1, 0),
              'S': (6, 6),
              'W': (3, 8),
              'grad_E': 52950,
              'grad_N': 19266,
              'grad_S': 27804,
              'grad_W': 30867},
     (0, 5): {'E': (0, 0),
              'N': (1, 2),
              'S': (6, 5),
              'W': (1, 2),
              'grad_E': 44478,
              'grad_N': 28713,
              'grad_S': 30069,
              'grad_W': 40545},
     (0, 6): {'E': (5, 8),
              'N': (7, 8),
              'S': (4, 5),
              'W': (7, 3),
              'grad_E': 52308,
              'grad_N': 34392,
              'grad_S': 36438,
              'grad_W': 52869},
     (0, 7): {'E': (2, 6),
              'N': (0, 8),
              'S': (0, 4),
              'W': (6, 5),
              'grad_E': 45441,
              'grad_N': 31599,
              'grad_S': 32523,
              'grad_W': 44442},
     (0, 8): {'E': (2, 5),
              'N': (1, 2),
              'S': (6, 5),
              'W': (5, 2),
              'grad_E': 49317,
              'grad_N': 29370,
              'grad_S': 23673,
              'grad_W': 49827},
     (1, 0): {'E': (3, 7),
              'N': (7, 1),
              'S': (3, 7),
              'W': (3, 8),
              'grad_E': 23916,
              'grad_N': 24186,
              'grad_S': 17082,
              'grad_W': 21441},
     (1, 1): {'E': (5, 8),
              'N': (1, 2),
              'S': (2, 5),
              'W': (8, 3),
              'grad_E': 51951,
              'grad_N': 29673,
              'grad_S': 35670,
              'grad_W': 48432},
     (1, 2): {'E': (0, 0),
              'N': (5, 2),
              'S': (0, 0),
              'W': (5, 2),
              'grad_E': 15123,
              'grad_N': 23979,
              'grad_S': 16542,
              'grad_W': 34635},
     (1, 3): {'E': (3, 8),
              'N': (1, 1),
              'S': (7, 1),
              'W': (1, 2),
              'grad_E': 52488,
              'grad_N': 36600,
              'grad_S': 33459,
              'grad_W': 50754},
     (1, 4): {'E': (2, 3),
              'N': (1, 0),
              'S': (4, 2),
              'W': (1, 5),
              'grad_E': 49386,
              'grad_N': 31650,
              'grad_S': 36540,
              'grad_W': 49659},
     (1, 5): {'E': (1, 0),
              'N': (5, 4),
              'S': (3, 7),
              'W': (3, 8),
              'grad_E': 27552,
              'grad_N': 36861,
              'grad_S': 15663,
              'grad_W': 48543},
     (1, 6): {'E': (2, 7),
              'N': (8, 8),
              'S': (8, 4),
              'W': (8, 7),
              'grad_E': 52257,
              'grad_N': 35334,
              'grad_S': 36519,
              'grad_W': 50718},
     (1, 7): {'E': (3, 1),
              'N': (1, 5),
              'S': (3, 8),
              'W': (0, 7),
              'grad_E': 44637,
              'grad_N': 34695,
              'grad_S': 19230,
              'grad_W': 46110},
     (1, 8): {'E': (6, 1),
              'N': (7, 8),
              'S': (6, 5),
              'W': (5, 3),
              'grad_E': 50040,
              'grad_N': 35562,
              'grad_S': 30210,
              'grad_W': 53343},
     (2, 0): {'E': (6, 2),
              'N': (7, 1),
              'S': (1, 3),
              'W': (2, 3),
              'grad_E': 51783,
              'grad_N': 31182,
              'grad_S': 37353,
              'grad_W': 50799},
     (2, 1): {'E': (4, 3),
              'N': (2, 5),
              'S': (5, 4),
              'W': (6, 5),
              'grad_E': 50169,
              'grad_N': 36132,
              'grad_S': 37410,
              'grad_W': 51636},
     (2, 2): {'E': (5, 0),
              'N': (6, 7),
              'S': (3, 7),
              'W': (7, 6),
              'grad_E': 51522,
              'grad_N': 34605,
              'grad_S': 36330,
              'grad_W': 50481},
     (2, 3): {'E': (3, 7),
              'N': (1, 0),
              'S': (7, 4),
              'W': (3, 8),
              'grad_E': 33711,
              'grad_N': 28383,
              'grad_S': 31080,
              'grad_W': 39723},
     (2, 4): {'E': (4, 5),
              'N': (5, 7),
              'S': (2, 7),
              'W': (7, 0),
              'grad_E': 52716,
              'grad_N': 33936,
              'grad_S': 37449,
              'grad_W': 51813},
     (2, 5): {'E': (8, 7),
              'N': (1, 2),
              'S': (6, 5),
              'W': (1, 2),
              'grad_E': 34845,
              'grad_N': 20934,
              'grad_S': 17436,
              'grad_W': 18843},
     (2, 6): {'E': (1, 0),
              'N': (7, 4),
              'S': (3, 7),
              'W': (1, 0),
              'grad_E': 21627,
              'grad_N': 33018,
              'grad_S': 15681,
              'grad_W': 24243},
     (2, 7): {'E': (3, 7),
              'N': (1, 3),
              'S': (3, 7),
              'W': (2, 3),
              'grad_E': 50040,
              'grad_N': 35946,
              'grad_S': 22440,
              'grad_W': 52026},
     (2, 8): {'E': (6, 7),
              'N': (5, 0),
              'S': (5, 2),
              'W': (5, 0),
              'grad_E': 41928,
              'grad_N': 27636,
              'grad_S': 26718,
              'grad_W': 27930},
     (3, 0): {'E': (6, 5),
              'N': (1, 7),
              'S': (1, 1),
              'W': (1, 3),
              'grad_E': 50100,
              'grad_N': 37926,
              'grad_S': 35559,
              'grad_W': 55404},
     (3, 1): {'E': (6, 3),
              'N': (7, 6),
              'S': (4, 6),
              'W': (6, 5),
              'grad_E': 45198,
              'grad_N': 23904,
              'grad_S': 24219,
              'grad_W': 39588},
     (3, 2): {'E': (4, 2),
              'N': (3, 8),
              'S': (6, 3),
              'W': (2, 8),
              'grad_E': 52257,
              'grad_N': 37338,
              'grad_S': 37011,
              'grad_W': 53106},
     (3, 3): {'E': (6, 4),
              'N': (7, 6),
              'S': (6, 6),
              'W': (7, 8),
              'grad_E': 54009,
              'grad_N': 28908,
              'grad_S': 37731,
              'grad_W': 51447},
     (3, 4): {'E': (0, 5),
              'N': (0, 8),
              'S': (5, 8),
              'W': (0, 0),
              'grad_E': 48630,
              'grad_N': 32289,
              'grad_S': 35121,
              'grad_W': 47748},
     (3, 5): {'E': (6, 5),
              'N': (8, 4),
              'S': (4, 6),
              'W': (0, 6),
              'grad_E': 48210,
              'grad_N': 37734,
              'grad_S': 36519,
              'grad_W': 53859},
     (3, 6): {'E': (2, 5),
              'N': (1, 2),
              'S': (0, 0),
              'W': (1, 2),
              'grad_E': 38499,
              'grad_N': 27273,
              'grad_S': 30774,
              'grad_W': 45723},
     (3, 7): {'E': (6, 6),
              'N': (1, 5),
              'S': (0, 4),
              'W': (7, 4),
              'grad_E': 36402,
              'grad_N': 15663,
              'grad_S': 26652,
              'grad_W': 23034},
     (3, 8): {'E': (1, 0),
              'N': (1, 0),
              'S': (4, 6),
              'W': (4, 1),
              'grad_E': 21441,
              'grad_N': 17508,
              'grad_S': 17874,
              'grad_W': 47616},
     (4, 0): {'E': (2, 6),
              'N': (7, 6),
              'S': (3, 1),
              'W': (4, 5),
              'grad_E': 45513,
              'grad_N': 30717,
              'grad_S': 32796,
              'grad_W': 49098},
     (4, 1): {'E': (2, 8),
              'N': (2, 8),
              'S': (5, 0),
              'W': (5, 0),
              'grad_E': 44667,
              'grad_N': 27312,
              'grad_S': 35004,
              'grad_W': 51090},
     (4, 2): {'E': (3, 7),
              'N': (1, 4),
              'S': (4, 6),
              'W': (6, 5),
              'grad_E': 49206,
              'grad_N': 36540,
              'grad_S': 30558,
              'grad_W': 49890},
     (4, 3): {'E': (4, 5),
              'N': (1, 2),
              'S': (4, 5),
              'W': (0, 0),
              'grad_E': 43836,
              'grad_N': 27606,
              'grad_S': 29397,
              'grad_W': 43539},
     (4, 4): {'E': (3, 6),
              'N': (8, 6),
              'S': (0, 3),
              'W': (7, 7),
              'grad_E': 52437,
              'grad_N': 37053,
              'grad_S': 36375,
              'grad_W': 54075},
     (4, 5): {'E': (6, 5),
              'N': (7, 6),
              'S': (6, 5),
              'W': (6, 5),
              'grad_E': 33171,
              'grad_N': 15063,
              'grad_S': 21111,
              'grad_W': 33984},
     (4, 6): {'E': (6, 6),
              'N': (3, 8),
              'S': (0, 4),
              'W': (4, 2),
              'grad_E': 31530,
              'grad_N': 17874,
              'grad_S': 29385,
              'grad_W': 54786},
     (4, 7): {'E': (3, 7),
              'N': (2, 3),
              'S': (7, 2),
              'W': (5, 0),
              'grad_E': 43419,
              'grad_N': 34578,
              'grad_S': 38052,
              'grad_W': 53739},
     (4, 8): {'E': (6, 4),
              'N': (1, 0),
              'S': (0, 0),
              'W': (1, 0),
              'grad_E': 52806,
              'grad_N': 31419,
              'grad_S': 36096,
              'grad_W': 28065},
     (5, 0): {'E': (2, 8),
              'N': (6, 7),
              'S': (6, 7),
              'W': (6, 7),
              'grad_E': 27930,
              'grad_N': 34869,
              'grad_S': 24480,
              'grad_W': 46704},
     (5, 1): {'E': (2, 5),
              'N': (6, 4),
              'S': (7, 6),
              'W': (6, 0),
              'grad_E': 38247,
              'grad_N': 35820,
              'grad_S': 36540,
              'grad_W': 52668},
     (5, 2): {'E': (1, 2),
              'N': (2, 8),
              'S': (1, 2),
              'W': (2, 8),
              'grad_E': 34635,
              'grad_N': 26718,
              'grad_S': 23979,
              'grad_W': 43293},
     (5, 3): {'E': (1, 8),
              'N': (6, 5),
              'S': (4, 5),
              'W': (7, 8),
              'grad_E': 53343,
              'grad_N': 34125,
              'grad_S': 35571,
              'grad_W': 52050},
     (5, 4): {'E': (1, 0),
              'N': (1, 5),
              'S': (4, 6),
              'W': (1, 0),
              'grad_E': 35379,
              'grad_N': 27828,
              'grad_S': 29037,
              'grad_W': 47622},
     (5, 5): {'E': (6, 6),
              'N': (6, 5),
              'S': (0, 0),
              'W': (8, 3),
              'grad_E': 51873,
              'grad_N': 33300,
              'grad_S': 36141,
              'grad_W': 52596},
     (5, 6): {'E': (1, 0),
              'N': (7, 1),
              'S': (0, 4),
              'W': (1, 0),
              'grad_E': 47148,
              'grad_N': 25566,
              'grad_S': 35811,
              'grad_W': 42957},
     (5, 7): {'E': (5, 4),
              'N': (1, 7),
              'S': (6, 5),
              'W': (6, 5),
              'grad_E': 49818,
              'grad_N': 37020,
              'grad_S': 22089,
              'grad_W': 37320},
     (5, 8): {'E': (2, 5),
              'N': (1, 2),
              'S': (6, 5),
              'W': (1, 1),
              'grad_E': 45390,
              'grad_N': 31473,
              'grad_S': 30168,
              'grad_W': 51951},
     (6, 0): {'E': (8, 7),
              'N': (2, 5),
              'S': (5, 0),
              'W': (1, 2),
              'grad_E': 33747,
              'grad_N': 27093,
              'grad_S': 36861,
              'grad_W': 49011},
     (6, 1): {'E': (8, 8),
              'N': (1, 8),
              'S': (4, 5),
              'W': (1, 8),
              'grad_E': 52917,
              'grad_N': 35364,
              'grad_S': 38391,
              'grad_W': 50040},
     (6, 2): {'E': (2, 6),
              'N': (0, 2),
              'S': (3, 7),
              'W': (1, 0),
              'grad_E': 33954,
              'grad_N': 38352,
              'grad_S': 23388,
              'grad_W': 50187},
     (6, 3): {'E': (6, 5),
              'N': (7, 8),
              'S': (0, 4),
              'W': (4, 5),
              'grad_E': 46689,
              'grad_N': 30774,
              'grad_S': 31761,
              'grad_W': 40488},
     (6, 4): {'E': (5, 1),
              'N': (6, 6),
              'S': (6, 5),
              'W': (1, 2),
              'grad_E': 54012,
              'grad_N': 37560,
              'grad_S': 31536,
              'grad_W': 37623},
     (6, 5): {'E': (0, 0),
              'N': (7, 6),
              'S': (4, 5),
              'W': (4, 5),
              'grad_E': 27462,
              'grad_N': 5091,
              'grad_S': 19866,
              'grad_W': 33171},
     (6, 6): {'E': (1, 2),
              'N': (0, 4),
              'S': (0, 5),
              'W': (7, 4),
              'grad_E': 50358,
              'grad_N': 27804,
              'grad_S': 34650,
              'grad_W': 29763},
     (6, 7): {'E': (2, 8),
              'N': (5, 0),
              'S': (2, 8),
              'W': (5, 0),
              'grad_E': 34335,
              'grad_N': 24480,
              'grad_S': 29322,
              'grad_W': 35601},
     (6, 8): {'E': (2, 2),
              'N': (0, 0),
              'S': (5, 2),
              'W': (8, 8),
              'grad_E': 52569,
              'grad_N': 38124,
              'grad_S': 36720,
              'grad_W': 52260},
     (7, 0): {'E': (1, 0),
              'N': (3, 0),
              'S': (4, 8),
              'W': (4, 5),
              'grad_E': 47058,
              'grad_N': 38547,
              'grad_S': 34362,
              'grad_W': 51093},
     (7, 1): {'E': (3, 7),
              'N': (1, 5),
              'S': (3, 8),
              'W': (7, 6),
              'grad_E': 35778,
              'grad_N': 15717,
              'grad_S': 18642,
              'grad_W': 54507},
     (7, 2): {'E': (0, 0),
              'N': (7, 6),
              'S': (6, 5),
              'W': (6, 5),
              'grad_E': 48147,
              'grad_N': 30222,
              'grad_S': 29976,
              'grad_W': 43332},
     (7, 3): {'E': (0, 8),
              'N': (7, 6),
              'S': (4, 5),
              'W': (1, 2),
              'grad_E': 50286,
              'grad_N': 33630,
              'grad_S': 33858,
              'grad_W': 48864},
     (7, 4): {'E': (3, 7),
              'N': (1, 5),
              'S': (3, 8),
              'W': (8, 0),
              'grad_E': 23034,
              'grad_N': 19374,
              'grad_S': 23001,
              'grad_W': 49974},
     (7, 5): {'E': (7, 3),
              'N': (8, 0),
              'S': (3, 7),
              'W': (4, 5),
              'grad_E': 55125,
              'grad_N': 35277,
              'grad_S': 35748,
              'grad_W': 50346},
     (7, 6): {'E': (6, 5),
              'N': (4, 3),
              'S': (6, 5),
              'W': (1, 2),
              'grad_E': 44496,
              'grad_N': 35139,
              'grad_S': 5091,
              'grad_W': 34587},
     (7, 7): {'E': (6, 7),
              'N': (5, 8),
              'S': (3, 6),
              'W': (5, 2),
              'grad_E': 52557,
              'grad_N': 36591,
              'grad_S': 35058,
              'grad_W': 49845},
     (7, 8): {'E': (6, 6),
              'N': (7, 6),
              'S': (3, 8),
              'W': (6, 5),
              'grad_E': 41283,
              'grad_N': 26022,
              'grad_S': 27216,
              'grad_W': 42456},
     (8, 0): {'E': (6, 5),
              'N': (6, 5),
              'S': (6, 5),
              'W': (1, 2),
              'grad_E': 44955,
              'grad_N': 31659,
              'grad_S': 27969,
              'grad_W': 39867},
     (8, 1): {'E': (6, 5),
              'N': (0, 3),
              'S': (2, 5),
              'W': (1, 6),
              'grad_E': 47445,
              'grad_N': 32412,
              'grad_S': 36021,
              'grad_W': 52257},
     (8, 2): {'E': (4, 8),
              'N': (0, 8),
              'S': (1, 0),
              'W': (7, 4),
              'grad_E': 46845,
              'grad_N': 36075,
              'grad_S': 30972,
              'grad_W': 53328},
     (8, 3): {'E': (1, 2),
              'N': (2, 8),
              'S': (2, 5),
              'W': (5, 2),
              'grad_E': 39915,
              'grad_N': 29970,
              'grad_S': 29100,
              'grad_W': 47946},
     (8, 4): {'E': (3, 1),
              'N': (1, 6),
              'S': (5, 6),
              'W': (7, 0),
              'grad_E': 52863,
              'grad_N': 36519,
              'grad_S': 36390,
              'grad_W': 53283},
     (8, 5): {'E': (0, 1),
              'N': (6, 4),
              'S': (5, 8),
              'W': (8, 6),
              'grad_E': 51903,
              'grad_N': 35913,
              'grad_S': 37149,
              'grad_W': 53082},
     (8, 6): {'E': (7, 7),
              'N': (2, 5),
              'S': (3, 6),
              'W': (5, 2),
              'grad_E': 52425,
              'grad_N': 33309,
              'grad_S': 33975,
              'grad_W': 51573},
     (8, 7): {'E': (6, 5),
              'N': (2, 5),
              'S': (3, 4),
              'W': (1, 2),
              'grad_E': 50709,
              'grad_N': 25320,
              'grad_S': 35352,
              'grad_W': 15474},
     (8, 8): {'E': (6, 8),
              'N': (6, 7),
              'S': (1, 6),
              'W': (8, 3),
              'grad_E': 52260,
              'grad_N': 33771,
              'grad_S': 35334,
              'grad_W': 48678}}

```python
ordered_list_east = getOrderedConfigsByConfig(dicBestConfig, orientation='E', reverse=False)
pprint(ordered_list_east)
```

    [((1, 2),
      {'E': (0, 0),
       'N': (5, 2),
       'S': (0, 0),
       'W': (5, 2),
       'grad_E': 15123,
       'grad_N': 23979,
       'grad_S': 16542,
       'grad_W': 34635}),
     ((3, 8),
      {'E': (1, 0),
       'N': (1, 0),
       'S': (4, 6),
       'W': (4, 1),
       'grad_E': 21441,
       'grad_N': 17508,
       'grad_S': 17874,
       'grad_W': 47616}),
     ((2, 6),
      {'E': (1, 0),
       'N': (7, 4),
       'S': (3, 7),
       'W': (1, 0),
       'grad_E': 21627,
       'grad_N': 33018,
       'grad_S': 15681,
       'grad_W': 24243}),
     ((7, 4),
      {'E': (3, 7),
       'N': (1, 5),
       'S': (3, 8),
       'W': (8, 0),
       'grad_E': 23034,
       'grad_N': 19374,
       'grad_S': 23001,
       'grad_W': 49974}),
     ((1, 0),
      {'E': (3, 7),
       'N': (7, 1),
       'S': (3, 7),
       'W': (3, 8),
       'grad_E': 23916,
       'grad_N': 24186,
       'grad_S': 17082,
       'grad_W': 21441}),
     ((6, 5),
      {'E': (0, 0),
       'N': (7, 6),
       'S': (4, 5),
       'W': (4, 5),
       'grad_E': 27462,
       'grad_N': 5091,
       'grad_S': 19866,
       'grad_W': 33171}),
     ((1, 5),
      {'E': (1, 0),
       'N': (5, 4),
       'S': (3, 7),
       'W': (3, 8),
       'grad_E': 27552,
       'grad_N': 36861,
       'grad_S': 15663,
       'grad_W': 48543}),
     ((5, 0),
      {'E': (2, 8),
       'N': (6, 7),
       'S': (6, 7),
       'W': (6, 7),
       'grad_E': 27930,
       'grad_N': 34869,
       'grad_S': 24480,
       'grad_W': 46704}),
     ((4, 6),
      {'E': (6, 6),
       'N': (3, 8),
       'S': (0, 4),
       'W': (4, 2),
       'grad_E': 31530,
       'grad_N': 17874,
       'grad_S': 29385,
       'grad_W': 54786}),
     ((4, 5),
      {'E': (6, 5),
       'N': (7, 6),
       'S': (6, 5),
       'W': (6, 5),
       'grad_E': 33171,
       'grad_N': 15063,
       'grad_S': 21111,
       'grad_W': 33984}),
     ((2, 3),
      {'E': (3, 7),
       'N': (1, 0),
       'S': (7, 4),
       'W': (3, 8),
       'grad_E': 33711,
       'grad_N': 28383,
       'grad_S': 31080,
       'grad_W': 39723}),
     ((6, 0),
      {'E': (8, 7),
       'N': (2, 5),
       'S': (5, 0),
       'W': (1, 2),
       'grad_E': 33747,
       'grad_N': 27093,
       'grad_S': 36861,
       'grad_W': 49011}),
     ((6, 2),
      {'E': (2, 6),
       'N': (0, 2),
       'S': (3, 7),
       'W': (1, 0),
       'grad_E': 33954,
       'grad_N': 38352,
       'grad_S': 23388,
       'grad_W': 50187}),
     ((6, 7),
      {'E': (2, 8),
       'N': (5, 0),
       'S': (2, 8),
       'W': (5, 0),
       'grad_E': 34335,
       'grad_N': 24480,
       'grad_S': 29322,
       'grad_W': 35601}),
     ((5, 2),
      {'E': (1, 2),
       'N': (2, 8),
       'S': (1, 2),
       'W': (2, 8),
       'grad_E': 34635,
       'grad_N': 26718,
       'grad_S': 23979,
       'grad_W': 43293}),
     ((2, 5),
      {'E': (8, 7),
       'N': (1, 2),
       'S': (6, 5),
       'W': (1, 2),
       'grad_E': 34845,
       'grad_N': 20934,
       'grad_S': 17436,
       'grad_W': 18843}),
     ((0, 3),
      {'E': (6, 5),
       'N': (7, 6),
       'S': (7, 4),
       'W': (6, 5),
       'grad_E': 34935,
       'grad_N': 25797,
       'grad_S': 30480,
       'grad_W': 45003}),
     ((5, 4),
      {'E': (1, 0),
       'N': (1, 5),
       'S': (4, 6),
       'W': (1, 0),
       'grad_E': 35379,
       'grad_N': 27828,
       'grad_S': 29037,
       'grad_W': 47622}),
     ((7, 1),
      {'E': (3, 7),
       'N': (1, 5),
       'S': (3, 8),
       'W': (7, 6),
       'grad_E': 35778,
       'grad_N': 15717,
       'grad_S': 18642,
       'grad_W': 54507}),
     ((3, 7),
      {'E': (6, 6),
       'N': (1, 5),
       'S': (0, 4),
       'W': (7, 4),
       'grad_E': 36402,
       'grad_N': 15663,
       'grad_S': 26652,
       'grad_W': 23034}),
     ((0, 0),
      {'E': (8, 7),
       'N': (1, 2),
       'S': (6, 5),
       'W': (1, 2),
       'grad_E': 37557,
       'grad_N': 16542,
       'grad_S': 24015,
       'grad_W': 15123}),
     ((5, 1),
      {'E': (2, 5),
       'N': (6, 4),
       'S': (7, 6),
       'W': (6, 0),
       'grad_E': 38247,
       'grad_N': 35820,
       'grad_S': 36540,
       'grad_W': 52668}),
     ((3, 6),
      {'E': (2, 5),
       'N': (1, 2),
       'S': (0, 0),
       'W': (1, 2),
       'grad_E': 38499,
       'grad_N': 27273,
       'grad_S': 30774,
       'grad_W': 45723}),
     ((8, 3),
      {'E': (1, 2),
       'N': (2, 8),
       'S': (2, 5),
       'W': (5, 2),
       'grad_E': 39915,
       'grad_N': 29970,
       'grad_S': 29100,
       'grad_W': 47946}),
     ((7, 8),
      {'E': (6, 6),
       'N': (7, 6),
       'S': (3, 8),
       'W': (6, 5),
       'grad_E': 41283,
       'grad_N': 26022,
       'grad_S': 27216,
       'grad_W': 42456}),
     ((2, 8),
      {'E': (6, 7),
       'N': (5, 0),
       'S': (5, 2),
       'W': (5, 0),
       'grad_E': 41928,
       'grad_N': 27636,
       'grad_S': 26718,
       'grad_W': 27930}),
     ((4, 7),
      {'E': (3, 7),
       'N': (2, 3),
       'S': (7, 2),
       'W': (5, 0),
       'grad_E': 43419,
       'grad_N': 34578,
       'grad_S': 38052,
       'grad_W': 53739}),
     ((4, 3),
      {'E': (4, 5),
       'N': (1, 2),
       'S': (4, 5),
       'W': (0, 0),
       'grad_E': 43836,
       'grad_N': 27606,
       'grad_S': 29397,
       'grad_W': 43539}),
     ((0, 5),
      {'E': (0, 0),
       'N': (1, 2),
       'S': (6, 5),
       'W': (1, 2),
       'grad_E': 44478,
       'grad_N': 28713,
       'grad_S': 30069,
       'grad_W': 40545}),
     ((7, 6),
      {'E': (6, 5),
       'N': (4, 3),
       'S': (6, 5),
       'W': (1, 2),
       'grad_E': 44496,
       'grad_N': 35139,
       'grad_S': 5091,
       'grad_W': 34587}),
     ((1, 7),
      {'E': (3, 1),
       'N': (1, 5),
       'S': (3, 8),
       'W': (0, 7),
       'grad_E': 44637,
       'grad_N': 34695,
       'grad_S': 19230,
       'grad_W': 46110}),
     ((4, 1),
      {'E': (2, 8),
       'N': (2, 8),
       'S': (5, 0),
       'W': (5, 0),
       'grad_E': 44667,
       'grad_N': 27312,
       'grad_S': 35004,
       'grad_W': 51090}),
     ((8, 0),
      {'E': (6, 5),
       'N': (6, 5),
       'S': (6, 5),
       'W': (1, 2),
       'grad_E': 44955,
       'grad_N': 31659,
       'grad_S': 27969,
       'grad_W': 39867}),
     ((3, 1),
      {'E': (6, 3),
       'N': (7, 6),
       'S': (4, 6),
       'W': (6, 5),
       'grad_E': 45198,
       'grad_N': 23904,
       'grad_S': 24219,
       'grad_W': 39588}),
     ((5, 8),
      {'E': (2, 5),
       'N': (1, 2),
       'S': (6, 5),
       'W': (1, 1),
       'grad_E': 45390,
       'grad_N': 31473,
       'grad_S': 30168,
       'grad_W': 51951}),
     ((0, 7),
      {'E': (2, 6),
       'N': (0, 8),
       'S': (0, 4),
       'W': (6, 5),
       'grad_E': 45441,
       'grad_N': 31599,
       'grad_S': 32523,
       'grad_W': 44442}),
     ((4, 0),
      {'E': (2, 6),
       'N': (7, 6),
       'S': (3, 1),
       'W': (4, 5),
       'grad_E': 45513,
       'grad_N': 30717,
       'grad_S': 32796,
       'grad_W': 49098}),
     ((6, 3),
      {'E': (6, 5),
       'N': (7, 8),
       'S': (0, 4),
       'W': (4, 5),
       'grad_E': 46689,
       'grad_N': 30774,
       'grad_S': 31761,
       'grad_W': 40488}),
     ((8, 2),
      {'E': (4, 8),
       'N': (0, 8),
       'S': (1, 0),
       'W': (7, 4),
       'grad_E': 46845,
       'grad_N': 36075,
       'grad_S': 30972,
       'grad_W': 53328}),
     ((7, 0),
      {'E': (1, 0),
       'N': (3, 0),
       'S': (4, 8),
       'W': (4, 5),
       'grad_E': 47058,
       'grad_N': 38547,
       'grad_S': 34362,
       'grad_W': 51093}),
     ((5, 6),
      {'E': (1, 0),
       'N': (7, 1),
       'S': (0, 4),
       'W': (1, 0),
       'grad_E': 47148,
       'grad_N': 25566,
       'grad_S': 35811,
       'grad_W': 42957}),
     ((8, 1),
      {'E': (6, 5),
       'N': (0, 3),
       'S': (2, 5),
       'W': (1, 6),
       'grad_E': 47445,
       'grad_N': 32412,
       'grad_S': 36021,
       'grad_W': 52257}),
     ((7, 2),
      {'E': (0, 0),
       'N': (7, 6),
       'S': (6, 5),
       'W': (6, 5),
       'grad_E': 48147,
       'grad_N': 30222,
       'grad_S': 29976,
       'grad_W': 43332}),
     ((3, 5),
      {'E': (6, 5),
       'N': (8, 4),
       'S': (4, 6),
       'W': (0, 6),
       'grad_E': 48210,
       'grad_N': 37734,
       'grad_S': 36519,
       'grad_W': 53859}),
     ((3, 4),
      {'E': (0, 5),
       'N': (0, 8),
       'S': (5, 8),
       'W': (0, 0),
       'grad_E': 48630,
       'grad_N': 32289,
       'grad_S': 35121,
       'grad_W': 47748}),
     ((4, 2),
      {'E': (3, 7),
       'N': (1, 4),
       'S': (4, 6),
       'W': (6, 5),
       'grad_E': 49206,
       'grad_N': 36540,
       'grad_S': 30558,
       'grad_W': 49890}),
     ((0, 8),
      {'E': (2, 5),
       'N': (1, 2),
       'S': (6, 5),
       'W': (5, 2),
       'grad_E': 49317,
       'grad_N': 29370,
       'grad_S': 23673,
       'grad_W': 49827}),
     ((1, 4),
      {'E': (2, 3),
       'N': (1, 0),
       'S': (4, 2),
       'W': (1, 5),
       'grad_E': 49386,
       'grad_N': 31650,
       'grad_S': 36540,
       'grad_W': 49659}),
     ((5, 7),
      {'E': (5, 4),
       'N': (1, 7),
       'S': (6, 5),
       'W': (6, 5),
       'grad_E': 49818,
       'grad_N': 37020,
       'grad_S': 22089,
       'grad_W': 37320}),
     ((1, 8),
      {'E': (6, 1),
       'N': (7, 8),
       'S': (6, 5),
       'W': (5, 3),
       'grad_E': 50040,
       'grad_N': 35562,
       'grad_S': 30210,
       'grad_W': 53343}),
     ((2, 7),
      {'E': (3, 7),
       'N': (1, 3),
       'S': (3, 7),
       'W': (2, 3),
       'grad_E': 50040,
       'grad_N': 35946,
       'grad_S': 22440,
       'grad_W': 52026}),
     ((3, 0),
      {'E': (6, 5),
       'N': (1, 7),
       'S': (1, 1),
       'W': (1, 3),
       'grad_E': 50100,
       'grad_N': 37926,
       'grad_S': 35559,
       'grad_W': 55404}),
     ((2, 1),
      {'E': (4, 3),
       'N': (2, 5),
       'S': (5, 4),
       'W': (6, 5),
       'grad_E': 50169,
       'grad_N': 36132,
       'grad_S': 37410,
       'grad_W': 51636}),
     ((7, 3),
      {'E': (0, 8),
       'N': (7, 6),
       'S': (4, 5),
       'W': (1, 2),
       'grad_E': 50286,
       'grad_N': 33630,
       'grad_S': 33858,
       'grad_W': 48864}),
     ((6, 6),
      {'E': (1, 2),
       'N': (0, 4),
       'S': (0, 5),
       'W': (7, 4),
       'grad_E': 50358,
       'grad_N': 27804,
       'grad_S': 34650,
       'grad_W': 29763}),
     ((8, 7),
      {'E': (6, 5),
       'N': (2, 5),
       'S': (3, 4),
       'W': (1, 2),
       'grad_E': 50709,
       'grad_N': 25320,
       'grad_S': 35352,
       'grad_W': 15474}),
     ((2, 2),
      {'E': (5, 0),
       'N': (6, 7),
       'S': (3, 7),
       'W': (7, 6),
       'grad_E': 51522,
       'grad_N': 34605,
       'grad_S': 36330,
       'grad_W': 50481}),
     ((2, 0),
      {'E': (6, 2),
       'N': (7, 1),
       'S': (1, 3),
       'W': (2, 3),
       'grad_E': 51783,
       'grad_N': 31182,
       'grad_S': 37353,
       'grad_W': 50799}),
     ((5, 5),
      {'E': (6, 6),
       'N': (6, 5),
       'S': (0, 0),
       'W': (8, 3),
       'grad_E': 51873,
       'grad_N': 33300,
       'grad_S': 36141,
       'grad_W': 52596}),
     ((8, 5),
      {'E': (0, 1),
       'N': (6, 4),
       'S': (5, 8),
       'W': (8, 6),
       'grad_E': 51903,
       'grad_N': 35913,
       'grad_S': 37149,
       'grad_W': 53082}),
     ((1, 1),
      {'E': (5, 8),
       'N': (1, 2),
       'S': (2, 5),
       'W': (8, 3),
       'grad_E': 51951,
       'grad_N': 29673,
       'grad_S': 35670,
       'grad_W': 48432}),
     ((1, 6),
      {'E': (2, 7),
       'N': (8, 8),
       'S': (8, 4),
       'W': (8, 7),
       'grad_E': 52257,
       'grad_N': 35334,
       'grad_S': 36519,
       'grad_W': 50718}),
     ((3, 2),
      {'E': (4, 2),
       'N': (3, 8),
       'S': (6, 3),
       'W': (2, 8),
       'grad_E': 52257,
       'grad_N': 37338,
       'grad_S': 37011,
       'grad_W': 53106}),
     ((8, 8),
      {'E': (6, 8),
       'N': (6, 7),
       'S': (1, 6),
       'W': (8, 3),
       'grad_E': 52260,
       'grad_N': 33771,
       'grad_S': 35334,
       'grad_W': 48678}),
     ((0, 6),
      {'E': (5, 8),
       'N': (7, 8),
       'S': (4, 5),
       'W': (7, 3),
       'grad_E': 52308,
       'grad_N': 34392,
       'grad_S': 36438,
       'grad_W': 52869}),
     ((8, 6),
      {'E': (7, 7),
       'N': (2, 5),
       'S': (3, 6),
       'W': (5, 2),
       'grad_E': 52425,
       'grad_N': 33309,
       'grad_S': 33975,
       'grad_W': 51573}),
     ((4, 4),
      {'E': (3, 6),
       'N': (8, 6),
       'S': (0, 3),
       'W': (7, 7),
       'grad_E': 52437,
       'grad_N': 37053,
       'grad_S': 36375,
       'grad_W': 54075}),
     ((0, 1),
      {'E': (0, 5),
       'N': (6, 7),
       'S': (0, 3),
       'W': (8, 5),
       'grad_E': 52467,
       'grad_N': 35199,
       'grad_S': 38364,
       'grad_W': 51903}),
     ((1, 3),
      {'E': (3, 8),
       'N': (1, 1),
       'S': (7, 1),
       'W': (1, 2),
       'grad_E': 52488,
       'grad_N': 36600,
       'grad_S': 33459,
       'grad_W': 50754}),
     ((0, 2),
      {'E': (7, 6),
       'N': (7, 2),
       'S': (0, 0),
       'W': (0, 3),
       'grad_E': 52557,
       'grad_N': 36384,
       'grad_S': 34899,
       'grad_W': 50661}),
     ((7, 7),
      {'E': (6, 7),
       'N': (5, 8),
       'S': (3, 6),
       'W': (5, 2),
       'grad_E': 52557,
       'grad_N': 36591,
       'grad_S': 35058,
       'grad_W': 49845}),
     ((6, 8),
      {'E': (2, 2),
       'N': (0, 0),
       'S': (5, 2),
       'W': (8, 8),
       'grad_E': 52569,
       'grad_N': 38124,
       'grad_S': 36720,
       'grad_W': 52260}),
     ((2, 4),
      {'E': (4, 5),
       'N': (5, 7),
       'S': (2, 7),
       'W': (7, 0),
       'grad_E': 52716,
       'grad_N': 33936,
       'grad_S': 37449,
       'grad_W': 51813}),
     ((4, 8),
      {'E': (6, 4),
       'N': (1, 0),
       'S': (0, 0),
       'W': (1, 0),
       'grad_E': 52806,
       'grad_N': 31419,
       'grad_S': 36096,
       'grad_W': 28065}),
     ((8, 4),
      {'E': (3, 1),
       'N': (1, 6),
       'S': (5, 6),
       'W': (7, 0),
       'grad_E': 52863,
       'grad_N': 36519,
       'grad_S': 36390,
       'grad_W': 53283}),
     ((6, 1),
      {'E': (8, 8),
       'N': (1, 8),
       'S': (4, 5),
       'W': (1, 8),
       'grad_E': 52917,
       'grad_N': 35364,
       'grad_S': 38391,
       'grad_W': 50040}),
     ((0, 4),
      {'E': (1, 5),
       'N': (1, 0),
       'S': (6, 6),
       'W': (3, 8),
       'grad_E': 52950,
       'grad_N': 19266,
       'grad_S': 27804,
       'grad_W': 30867}),
     ((5, 3),
      {'E': (1, 8),
       'N': (6, 5),
       'S': (4, 5),
       'W': (7, 8),
       'grad_E': 53343,
       'grad_N': 34125,
       'grad_S': 35571,
       'grad_W': 52050}),
     ((3, 3),
      {'E': (6, 4),
       'N': (7, 6),
       'S': (6, 6),
       'W': (7, 8),
       'grad_E': 54009,
       'grad_N': 28908,
       'grad_S': 37731,
       'grad_W': 51447}),
     ((6, 4),
      {'E': (5, 1),
       'N': (6, 6),
       'S': (6, 5),
       'W': (1, 2),
       'grad_E': 54012,
       'grad_N': 37560,
       'grad_S': 31536,
       'grad_W': 37623}),
     ((7, 5),
      {'E': (7, 3),
       'N': (8, 0),
       'S': (3, 7),
       'W': (4, 5),
       'grad_E': 55125,
       'grad_N': 35277,
       'grad_S': 35748,
       'grad_W': 50346})]

```python
ordered_list = getOrderedConfigs(dicBestConfig, reverse=False)
ordered_list
```

    [Config(start=(6, 5), end=(7, 6), orientation='N', score=5091),
     Config(start=(7, 6), end=(6, 5), orientation='S', score=5091),
     Config(start=(4, 5), end=(7, 6), orientation='N', score=15063),
     Config(start=(0, 0), end=(1, 2), orientation='W', score=15123),
     Config(start=(1, 2), end=(0, 0), orientation='E', score=15123),
     Config(start=(8, 7), end=(1, 2), orientation='W', score=15474),
     Config(start=(1, 5), end=(3, 7), orientation='S', score=15663),
     Config(start=(3, 7), end=(1, 5), orientation='N', score=15663),
     Config(start=(2, 6), end=(3, 7), orientation='S', score=15681),
     Config(start=(7, 1), end=(1, 5), orientation='N', score=15717),
     Config(start=(0, 0), end=(1, 2), orientation='N', score=16542),
     Config(start=(1, 2), end=(0, 0), orientation='S', score=16542),
     Config(start=(1, 0), end=(3, 7), orientation='S', score=17082),
     Config(start=(2, 5), end=(6, 5), orientation='S', score=17436),
     Config(start=(3, 8), end=(1, 0), orientation='N', score=17508),
     Config(start=(3, 8), end=(4, 6), orientation='S', score=17874),
     Config(start=(4, 6), end=(3, 8), orientation='N', score=17874),
     Config(start=(7, 1), end=(3, 8), orientation='S', score=18642),
     Config(start=(2, 5), end=(1, 2), orientation='W', score=18843),
     Config(start=(1, 7), end=(3, 8), orientation='S', score=19230),
     Config(start=(0, 4), end=(1, 0), orientation='N', score=19266),
     Config(start=(7, 4), end=(1, 5), orientation='N', score=19374),
     Config(start=(6, 5), end=(4, 5), orientation='S', score=19866),
     Config(start=(2, 5), end=(1, 2), orientation='N', score=20934),
     Config(start=(4, 5), end=(6, 5), orientation='S', score=21111),
     Config(start=(1, 0), end=(3, 8), orientation='W', score=21441),
     Config(start=(3, 8), end=(1, 0), orientation='E', score=21441),
     Config(start=(2, 6), end=(1, 0), orientation='E', score=21627),
     Config(start=(5, 7), end=(6, 5), orientation='S', score=22089),
     Config(start=(2, 7), end=(3, 7), orientation='S', score=22440),
     Config(start=(7, 4), end=(3, 8), orientation='S', score=23001),
     Config(start=(3, 7), end=(7, 4), orientation='W', score=23034),
     Config(start=(7, 4), end=(3, 7), orientation='E', score=23034),
     Config(start=(6, 2), end=(3, 7), orientation='S', score=23388),
     Config(start=(0, 8), end=(6, 5), orientation='S', score=23673),
     Config(start=(3, 1), end=(7, 6), orientation='N', score=23904),
     Config(start=(1, 0), end=(3, 7), orientation='E', score=23916),
     Config(start=(1, 2), end=(5, 2), orientation='N', score=23979),
     Config(start=(5, 2), end=(1, 2), orientation='S', score=23979),
     Config(start=(0, 0), end=(6, 5), orientation='S', score=24015),
     Config(start=(1, 0), end=(7, 1), orientation='N', score=24186),
     Config(start=(3, 1), end=(4, 6), orientation='S', score=24219),
     Config(start=(2, 6), end=(1, 0), orientation='W', score=24243),
     Config(start=(5, 0), end=(6, 7), orientation='S', score=24480),
     Config(start=(6, 7), end=(5, 0), orientation='N', score=24480),
     Config(start=(8, 7), end=(2, 5), orientation='N', score=25320),
     Config(start=(5, 6), end=(7, 1), orientation='N', score=25566),
     Config(start=(0, 3), end=(7, 6), orientation='N', score=25797),
     Config(start=(7, 8), end=(7, 6), orientation='N', score=26022),
     Config(start=(3, 7), end=(0, 4), orientation='S', score=26652),
     Config(start=(2, 8), end=(5, 2), orientation='S', score=26718),
     Config(start=(5, 2), end=(2, 8), orientation='N', score=26718),
     Config(start=(6, 0), end=(2, 5), orientation='N', score=27093),
     Config(start=(7, 8), end=(3, 8), orientation='S', score=27216),
     Config(start=(3, 6), end=(1, 2), orientation='N', score=27273),
     Config(start=(4, 1), end=(2, 8), orientation='N', score=27312),
     Config(start=(6, 5), end=(0, 0), orientation='E', score=27462),
     Config(start=(1, 5), end=(1, 0), orientation='E', score=27552),
     Config(start=(4, 3), end=(1, 2), orientation='N', score=27606),
     Config(start=(2, 8), end=(5, 0), orientation='N', score=27636),
     Config(start=(0, 4), end=(6, 6), orientation='S', score=27804),
     Config(start=(6, 6), end=(0, 4), orientation='N', score=27804),
     Config(start=(5, 4), end=(1, 5), orientation='N', score=27828),
     Config(start=(2, 8), end=(5, 0), orientation='W', score=27930),
     Config(start=(5, 0), end=(2, 8), orientation='E', score=27930),
     Config(start=(8, 0), end=(6, 5), orientation='S', score=27969),
     Config(start=(4, 8), end=(1, 0), orientation='W', score=28065),
     Config(start=(2, 3), end=(1, 0), orientation='N', score=28383),
     Config(start=(0, 5), end=(1, 2), orientation='N', score=28713),
     Config(start=(3, 3), end=(7, 6), orientation='N', score=28908),
     Config(start=(5, 4), end=(4, 6), orientation='S', score=29037),
     Config(start=(8, 3), end=(2, 5), orientation='S', score=29100),
     Config(start=(6, 7), end=(2, 8), orientation='S', score=29322),
     Config(start=(0, 8), end=(1, 2), orientation='N', score=29370),
     Config(start=(4, 6), end=(0, 4), orientation='S', score=29385),
     Config(start=(4, 3), end=(4, 5), orientation='S', score=29397),
     Config(start=(1, 1), end=(1, 2), orientation='N', score=29673),
     Config(start=(6, 6), end=(7, 4), orientation='W', score=29763),
     Config(start=(8, 3), end=(2, 8), orientation='N', score=29970),
     Config(start=(7, 2), end=(6, 5), orientation='S', score=29976),
     Config(start=(0, 5), end=(6, 5), orientation='S', score=30069),
     Config(start=(5, 8), end=(6, 5), orientation='S', score=30168),
     Config(start=(1, 8), end=(6, 5), orientation='S', score=30210),
     Config(start=(7, 2), end=(7, 6), orientation='N', score=30222),
     Config(start=(0, 3), end=(7, 4), orientation='S', score=30480),
     Config(start=(4, 2), end=(4, 6), orientation='S', score=30558),
     Config(start=(4, 0), end=(7, 6), orientation='N', score=30717),
     Config(start=(3, 6), end=(0, 0), orientation='S', score=30774),
     Config(start=(6, 3), end=(7, 8), orientation='N', score=30774),
     Config(start=(0, 4), end=(3, 8), orientation='W', score=30867),
     Config(start=(8, 2), end=(1, 0), orientation='S', score=30972),
     Config(start=(2, 3), end=(7, 4), orientation='S', score=31080),
     Config(start=(2, 0), end=(7, 1), orientation='N', score=31182),
     Config(start=(4, 8), end=(1, 0), orientation='N', score=31419),
     Config(start=(5, 8), end=(1, 2), orientation='N', score=31473),
     Config(start=(4, 6), end=(6, 6), orientation='E', score=31530),
     Config(start=(6, 4), end=(6, 5), orientation='S', score=31536),
     Config(start=(0, 7), end=(0, 8), orientation='N', score=31599),
     Config(start=(1, 4), end=(1, 0), orientation='N', score=31650),
     Config(start=(8, 0), end=(6, 5), orientation='N', score=31659),
     Config(start=(6, 3), end=(0, 4), orientation='S', score=31761),
     Config(start=(3, 4), end=(0, 8), orientation='N', score=32289),
     Config(start=(8, 1), end=(0, 3), orientation='N', score=32412),
     Config(start=(0, 7), end=(0, 4), orientation='S', score=32523),
     Config(start=(4, 0), end=(3, 1), orientation='S', score=32796),
     Config(start=(2, 6), end=(7, 4), orientation='N', score=33018),
     Config(start=(4, 5), end=(6, 5), orientation='E', score=33171),
     Config(start=(6, 5), end=(4, 5), orientation='W', score=33171),
     Config(start=(5, 5), end=(6, 5), orientation='N', score=33300),
     Config(start=(8, 6), end=(2, 5), orientation='N', score=33309),
     Config(start=(1, 3), end=(7, 1), orientation='S', score=33459),
     Config(start=(7, 3), end=(7, 6), orientation='N', score=33630),
     Config(start=(2, 3), end=(3, 7), orientation='E', score=33711),
     Config(start=(6, 0), end=(8, 7), orientation='E', score=33747),
     Config(start=(8, 8), end=(6, 7), orientation='N', score=33771),
     Config(start=(7, 3), end=(4, 5), orientation='S', score=33858),
     Config(start=(2, 4), end=(5, 7), orientation='N', score=33936),
     Config(start=(6, 2), end=(2, 6), orientation='E', score=33954),
     Config(start=(8, 6), end=(3, 6), orientation='S', score=33975),
     Config(start=(4, 5), end=(6, 5), orientation='W', score=33984),
     Config(start=(5, 3), end=(6, 5), orientation='N', score=34125),
     Config(start=(6, 7), end=(2, 8), orientation='E', score=34335),
     Config(start=(7, 0), end=(4, 8), orientation='S', score=34362),
     Config(start=(0, 6), end=(7, 8), orientation='N', score=34392),
     Config(start=(4, 7), end=(2, 3), orientation='N', score=34578),
     Config(start=(7, 6), end=(1, 2), orientation='W', score=34587),
     Config(start=(2, 2), end=(6, 7), orientation='N', score=34605),
     Config(start=(1, 2), end=(5, 2), orientation='W', score=34635),
     Config(start=(5, 2), end=(1, 2), orientation='E', score=34635),
     Config(start=(6, 6), end=(0, 5), orientation='S', score=34650),
     Config(start=(1, 7), end=(1, 5), orientation='N', score=34695),
     Config(start=(2, 5), end=(8, 7), orientation='E', score=34845),
     Config(start=(5, 0), end=(6, 7), orientation='N', score=34869),
     Config(start=(0, 2), end=(0, 0), orientation='S', score=34899),
     Config(start=(0, 3), end=(6, 5), orientation='E', score=34935),
     Config(start=(4, 1), end=(5, 0), orientation='S', score=35004),
     Config(start=(7, 7), end=(3, 6), orientation='S', score=35058),
     Config(start=(3, 4), end=(5, 8), orientation='S', score=35121),
     Config(start=(7, 6), end=(4, 3), orientation='N', score=35139),
     Config(start=(0, 1), end=(6, 7), orientation='N', score=35199),
     Config(start=(7, 5), end=(8, 0), orientation='N', score=35277),
     Config(start=(1, 6), end=(8, 8), orientation='N', score=35334),
     Config(start=(8, 8), end=(1, 6), orientation='S', score=35334),
     Config(start=(8, 7), end=(3, 4), orientation='S', score=35352),
     Config(start=(6, 1), end=(1, 8), orientation='N', score=35364),
     Config(start=(5, 4), end=(1, 0), orientation='E', score=35379),
     Config(start=(3, 0), end=(1, 1), orientation='S', score=35559),
     Config(start=(1, 8), end=(7, 8), orientation='N', score=35562),
     Config(start=(5, 3), end=(4, 5), orientation='S', score=35571),
     Config(start=(6, 7), end=(5, 0), orientation='W', score=35601),
     Config(start=(1, 1), end=(2, 5), orientation='S', score=35670),
     Config(start=(7, 5), end=(3, 7), orientation='S', score=35748),
     Config(start=(7, 1), end=(3, 7), orientation='E', score=35778),
     Config(start=(5, 6), end=(0, 4), orientation='S', score=35811),
     Config(start=(5, 1), end=(6, 4), orientation='N', score=35820),
     Config(start=(8, 5), end=(6, 4), orientation='N', score=35913),
     Config(start=(2, 7), end=(1, 3), orientation='N', score=35946),
     Config(start=(8, 1), end=(2, 5), orientation='S', score=36021),
     Config(start=(8, 2), end=(0, 8), orientation='N', score=36075),
     Config(start=(4, 8), end=(0, 0), orientation='S', score=36096),
     Config(start=(2, 1), end=(2, 5), orientation='N', score=36132),
     Config(start=(5, 5), end=(0, 0), orientation='S', score=36141),
     Config(start=(2, 2), end=(3, 7), orientation='S', score=36330),
     Config(start=(4, 4), end=(0, 3), orientation='S', score=36375),
     Config(start=(0, 2), end=(7, 2), orientation='N', score=36384),
     Config(start=(8, 4), end=(5, 6), orientation='S', score=36390),
     Config(start=(3, 7), end=(6, 6), orientation='E', score=36402),
     Config(start=(0, 6), end=(4, 5), orientation='S', score=36438),
     Config(start=(1, 6), end=(8, 4), orientation='S', score=36519),
     Config(start=(3, 5), end=(4, 6), orientation='S', score=36519),
     Config(start=(8, 4), end=(1, 6), orientation='N', score=36519),
     Config(start=(1, 4), end=(4, 2), orientation='S', score=36540),
     Config(start=(4, 2), end=(1, 4), orientation='N', score=36540),
     Config(start=(5, 1), end=(7, 6), orientation='S', score=36540),
     Config(start=(7, 7), end=(5, 8), orientation='N', score=36591),
     Config(start=(1, 3), end=(1, 1), orientation='N', score=36600),
     Config(start=(6, 8), end=(5, 2), orientation='S', score=36720),
     Config(start=(1, 5), end=(5, 4), orientation='N', score=36861),
     Config(start=(6, 0), end=(5, 0), orientation='S', score=36861),
     Config(start=(3, 2), end=(6, 3), orientation='S', score=37011),
     Config(start=(5, 7), end=(1, 7), orientation='N', score=37020),
     Config(start=(4, 4), end=(8, 6), orientation='N', score=37053),
     Config(start=(8, 5), end=(5, 8), orientation='S', score=37149),
     Config(start=(5, 7), end=(6, 5), orientation='W', score=37320),
     Config(start=(3, 2), end=(3, 8), orientation='N', score=37338),
     Config(start=(2, 0), end=(1, 3), orientation='S', score=37353),
     Config(start=(2, 1), end=(5, 4), orientation='S', score=37410),
     Config(start=(2, 4), end=(2, 7), orientation='S', score=37449),
     Config(start=(0, 0), end=(8, 7), orientation='E', score=37557),
     Config(start=(6, 4), end=(6, 6), orientation='N', score=37560),
     Config(start=(6, 4), end=(1, 2), orientation='W', score=37623),
     Config(start=(3, 3), end=(6, 6), orientation='S', score=37731),
     Config(start=(3, 5), end=(8, 4), orientation='N', score=37734),
     Config(start=(3, 0), end=(1, 7), orientation='N', score=37926),
     Config(start=(4, 7), end=(7, 2), orientation='S', score=38052),
     Config(start=(6, 8), end=(0, 0), orientation='N', score=38124),
     Config(start=(5, 1), end=(2, 5), orientation='E', score=38247),
     Config(start=(6, 2), end=(0, 2), orientation='N', score=38352),
     Config(start=(0, 1), end=(0, 3), orientation='S', score=38364),
     Config(start=(6, 1), end=(4, 5), orientation='S', score=38391),
     Config(start=(3, 6), end=(2, 5), orientation='E', score=38499),
     Config(start=(7, 0), end=(3, 0), orientation='N', score=38547),
     Config(start=(3, 1), end=(6, 5), orientation='W', score=39588),
     Config(start=(2, 3), end=(3, 8), orientation='W', score=39723),
     Config(start=(8, 0), end=(1, 2), orientation='W', score=39867),
     Config(start=(8, 3), end=(1, 2), orientation='E', score=39915),
     Config(start=(6, 3), end=(4, 5), orientation='W', score=40488),
     Config(start=(0, 5), end=(1, 2), orientation='W', score=40545),
     Config(start=(7, 8), end=(6, 6), orientation='E', score=41283),
     Config(start=(2, 8), end=(6, 7), orientation='E', score=41928),
     Config(start=(7, 8), end=(6, 5), orientation='W', score=42456),
     Config(start=(5, 6), end=(1, 0), orientation='W', score=42957),
     Config(start=(5, 2), end=(2, 8), orientation='W', score=43293),
     Config(start=(7, 2), end=(6, 5), orientation='W', score=43332),
     Config(start=(4, 7), end=(3, 7), orientation='E', score=43419),
     Config(start=(4, 3), end=(0, 0), orientation='W', score=43539),
     Config(start=(4, 3), end=(4, 5), orientation='E', score=43836),
     Config(start=(0, 7), end=(6, 5), orientation='W', score=44442),
     Config(start=(0, 5), end=(0, 0), orientation='E', score=44478),
     Config(start=(7, 6), end=(6, 5), orientation='E', score=44496),
     Config(start=(1, 7), end=(3, 1), orientation='E', score=44637),
     Config(start=(4, 1), end=(2, 8), orientation='E', score=44667),
     Config(start=(8, 0), end=(6, 5), orientation='E', score=44955),
     Config(start=(0, 3), end=(6, 5), orientation='W', score=45003),
     Config(start=(3, 1), end=(6, 3), orientation='E', score=45198),
     Config(start=(5, 8), end=(2, 5), orientation='E', score=45390),
     Config(start=(0, 7), end=(2, 6), orientation='E', score=45441),
     Config(start=(4, 0), end=(2, 6), orientation='E', score=45513),
     Config(start=(3, 6), end=(1, 2), orientation='W', score=45723),
     Config(start=(1, 7), end=(0, 7), orientation='W', score=46110),
     Config(start=(6, 3), end=(6, 5), orientation='E', score=46689),
     Config(start=(5, 0), end=(6, 7), orientation='W', score=46704),
     Config(start=(8, 2), end=(4, 8), orientation='E', score=46845),
     Config(start=(7, 0), end=(1, 0), orientation='E', score=47058),
     Config(start=(5, 6), end=(1, 0), orientation='E', score=47148),
     Config(start=(8, 1), end=(6, 5), orientation='E', score=47445),
     Config(start=(3, 8), end=(4, 1), orientation='W', score=47616),
     Config(start=(5, 4), end=(1, 0), orientation='W', score=47622),
     Config(start=(3, 4), end=(0, 0), orientation='W', score=47748),
     Config(start=(8, 3), end=(5, 2), orientation='W', score=47946),
     Config(start=(7, 2), end=(0, 0), orientation='E', score=48147),
     Config(start=(3, 5), end=(6, 5), orientation='E', score=48210),
     Config(start=(1, 1), end=(8, 3), orientation='W', score=48432),
     Config(start=(1, 5), end=(3, 8), orientation='W', score=48543),
     Config(start=(3, 4), end=(0, 5), orientation='E', score=48630),
     Config(start=(8, 8), end=(8, 3), orientation='W', score=48678),
     Config(start=(7, 3), end=(1, 2), orientation='W', score=48864),
     Config(start=(6, 0), end=(1, 2), orientation='W', score=49011),
     Config(start=(4, 0), end=(4, 5), orientation='W', score=49098),
     Config(start=(4, 2), end=(3, 7), orientation='E', score=49206),
     Config(start=(0, 8), end=(2, 5), orientation='E', score=49317),
     Config(start=(1, 4), end=(2, 3), orientation='E', score=49386),
     Config(start=(1, 4), end=(1, 5), orientation='W', score=49659),
     Config(start=(5, 7), end=(5, 4), orientation='E', score=49818),
     Config(start=(0, 8), end=(5, 2), orientation='W', score=49827),
     Config(start=(7, 7), end=(5, 2), orientation='W', score=49845),
     Config(start=(4, 2), end=(6, 5), orientation='W', score=49890),
     Config(start=(7, 4), end=(8, 0), orientation='W', score=49974),
     Config(start=(1, 8), end=(6, 1), orientation='E', score=50040),
     Config(start=(2, 7), end=(3, 7), orientation='E', score=50040),
     Config(start=(6, 1), end=(1, 8), orientation='W', score=50040),
     Config(start=(3, 0), end=(6, 5), orientation='E', score=50100),
     Config(start=(2, 1), end=(4, 3), orientation='E', score=50169),
     Config(start=(6, 2), end=(1, 0), orientation='W', score=50187),
     Config(start=(7, 3), end=(0, 8), orientation='E', score=50286),
     Config(start=(7, 5), end=(4, 5), orientation='W', score=50346),
     Config(start=(6, 6), end=(1, 2), orientation='E', score=50358),
     Config(start=(2, 2), end=(7, 6), orientation='W', score=50481),
     Config(start=(0, 2), end=(0, 3), orientation='W', score=50661),
     Config(start=(8, 7), end=(6, 5), orientation='E', score=50709),
     Config(start=(1, 6), end=(8, 7), orientation='W', score=50718),
     Config(start=(1, 3), end=(1, 2), orientation='W', score=50754),
     Config(start=(2, 0), end=(2, 3), orientation='W', score=50799),
     Config(start=(4, 1), end=(5, 0), orientation='W', score=51090),
     Config(start=(7, 0), end=(4, 5), orientation='W', score=51093),
     Config(start=(3, 3), end=(7, 8), orientation='W', score=51447),
     Config(start=(2, 2), end=(5, 0), orientation='E', score=51522),
     Config(start=(8, 6), end=(5, 2), orientation='W', score=51573),
     Config(start=(2, 1), end=(6, 5), orientation='W', score=51636),
     Config(start=(2, 0), end=(6, 2), orientation='E', score=51783),
     Config(start=(2, 4), end=(7, 0), orientation='W', score=51813),
     Config(start=(5, 5), end=(6, 6), orientation='E', score=51873),
     Config(start=(0, 1), end=(8, 5), orientation='W', score=51903),
     Config(start=(8, 5), end=(0, 1), orientation='E', score=51903),
     Config(start=(1, 1), end=(5, 8), orientation='E', score=51951),
     Config(start=(5, 8), end=(1, 1), orientation='W', score=51951),
     Config(start=(2, 7), end=(2, 3), orientation='W', score=52026),
     Config(start=(5, 3), end=(7, 8), orientation='W', score=52050),
     Config(start=(1, 6), end=(2, 7), orientation='E', score=52257),
     Config(start=(3, 2), end=(4, 2), orientation='E', score=52257),
     Config(start=(8, 1), end=(1, 6), orientation='W', score=52257),
     Config(start=(6, 8), end=(8, 8), orientation='W', score=52260),
     Config(start=(8, 8), end=(6, 8), orientation='E', score=52260),
     Config(start=(0, 6), end=(5, 8), orientation='E', score=52308),
     Config(start=(8, 6), end=(7, 7), orientation='E', score=52425),
     Config(start=(4, 4), end=(3, 6), orientation='E', score=52437),
     Config(start=(0, 1), end=(0, 5), orientation='E', score=52467),
     Config(start=(1, 3), end=(3, 8), orientation='E', score=52488),
     Config(start=(0, 2), end=(7, 6), orientation='E', score=52557),
     Config(start=(7, 7), end=(6, 7), orientation='E', score=52557),
     Config(start=(6, 8), end=(2, 2), orientation='E', score=52569),
     Config(start=(5, 5), end=(8, 3), orientation='W', score=52596),
     Config(start=(5, 1), end=(6, 0), orientation='W', score=52668),
     Config(start=(2, 4), end=(4, 5), orientation='E', score=52716),
     Config(start=(4, 8), end=(6, 4), orientation='E', score=52806),
     Config(start=(8, 4), end=(3, 1), orientation='E', score=52863),
     Config(start=(0, 6), end=(7, 3), orientation='W', score=52869),
     Config(start=(6, 1), end=(8, 8), orientation='E', score=52917),
     Config(start=(0, 4), end=(1, 5), orientation='E', score=52950),
     Config(start=(8, 5), end=(8, 6), orientation='W', score=53082),
     Config(start=(3, 2), end=(2, 8), orientation='W', score=53106),
     Config(start=(8, 4), end=(7, 0), orientation='W', score=53283),
     Config(start=(8, 2), end=(7, 4), orientation='W', score=53328),
     Config(start=(1, 8), end=(5, 3), orientation='W', score=53343),
     Config(start=(5, 3), end=(1, 8), orientation='E', score=53343),
     Config(start=(4, 7), end=(5, 0), orientation='W', score=53739),
     Config(start=(3, 5), end=(0, 6), orientation='W', score=53859),
     Config(start=(3, 3), end=(6, 4), orientation='E', score=54009),
     Config(start=(6, 4), end=(5, 1), orientation='E', score=54012),
     Config(start=(4, 4), end=(7, 7), orientation='W', score=54075),
     Config(start=(7, 1), end=(7, 6), orientation='W', score=54507),
     Config(start=(4, 6), end=(4, 2), orientation='W', score=54786),
     Config(start=(7, 5), end=(7, 3), orientation='E', score=55125),
     Config(start=(3, 0), end=(1, 3), orientation='W', score=55404)]

# Résolution par backtracking

## Initialisation

**Préliminaire:** Pour que l'algorithme de backtracking soit efficace, il faut commencer d'un puzzle bien entamé pour pouvoir couper au plus tôt les branches non-intéressantes. On se propose alors de créer une fonction qui permet mouvoir soit-même les pièces pour le rendre en un temps restreint le plus homogène possible.

```python
coords_1 = (0,0)
coords_2 = (1,0)

config_switcher_helper(cropped, nb_lines, nb_cols, coords_1, coords_2)
```

```python
def launch_widget(cropped, nb_lines, nb_cols):
    # Global varibles
    global old_cropped, new_cropped, new_image
    old_cropped = deepcopy(cropped)
    new_cropped = deepcopy(cropped)
    original_image = cropped_to_img(cropped, nb_lines, nb_cols)
    new_image = None

    display_image(original_image, nb_lines, nb_cols, title='Original Image', figsize=(6,12))

    # --------- Defining widgets ---------
    x_old_widget = widgets.Dropdown(
        options=[str(i) for i in range(nb_lines)],
        value='0',
        description='x_old:',
        disabled=False,
    )

    y_old_widget = widgets.Dropdown(
        options=[str(i) for i in range(nb_lines)],
        value='0',
        description='y_old:',
        disabled=False,
    )

    x_new_widget = widgets.Dropdown(
        options=[str(i) for i in range(nb_lines)],
        value='0',
        description='x_new:',
        disabled=False,
    )

    y_new_widget = widgets.Dropdown(
        options=[str(i) for i in range(nb_lines)],
        value='0',
        description='y_new:',
        disabled=False,
    )

    list_coords_dropdown = [x_old_widget, y_old_widget, x_new_widget, y_new_widget]

    box_coords = widgets.HBox(children=list_coords_dropdown)

    apply_button = widgets.Button(
        description='Apply',
    )

    # --------- Defining buttons ---------
    @apply_button.on_click
    def apply_on_click(b=None):
        global old_cropped, new_cropped, new_image

        clear_output(wait=True)
        display(box_final)

        old_cropped = deepcopy(new_cropped)

        x_old = int(x_old_widget.value)
        y_old = int(y_old_widget.value)
        x_new = int(x_new_widget.value)
        y_new = int(y_new_widget.value)

        # The following coords are given with the index and not with the plt
        # coords system!
        coords_old = (x_old, y_old)
        coords_new = (x_new, y_new)

        print(f'coords_old={coords_old}, coords_new={coords_new}')

        plt.figure(figsize=(12, 10))

        # ---------- 1st sublot: Original Image ----------
        ax = plt.subplot(1, 2, 1)
        old_image = cropped_to_img(old_cropped, nb_lines, nb_cols)

        xticks_location = (old_image.width / nb_cols) / 2 + np.linspace(0, old_image.width, nb_cols+1)
        yticks_location = (old_image.height / nb_lines) / 2 + np.linspace(0, old_image.height, nb_lines+1)

        plt.imshow(old_image)
        plt.xticks(xticks_location, range(nb_cols))
        plt.yticks(yticks_location, range(nb_lines))
        plt.title('Old image')

        # Create a Rectangle patch
        # NB: 1st argument of patches.Rectangle gives the coords of the upper left
        # vertex of the rectangle.
        piece_height = old_image.height / nb_lines
        piece_width = old_image.width / nb_cols

        xy_rect_old = (x_old * piece_width, y_old * piece_height)
        xy_rect_new = (x_new * piece_width, y_new * piece_height)

        rect_old = patches.Rectangle(xy=xy_rect_old,
                                     width=piece_width,
                                     height=piece_height,
                                     linewidth=3,
                                     edgecolor='red',
                                     facecolor='none')

        rect_new = patches.Rectangle(xy=xy_rect_new,
                                     width=piece_width,
                                     height=piece_height,
                                     linewidth=3,
                                     edgecolor='green',
                                     facecolor='none')

        # Add the patches to the Axes
        ax.add_patch(rect_old)
        ax.add_patch(rect_new)

        # ---------- 2nd sublot: New Image ----------
        ax = plt.subplot(1, 2, 2)
        new_cropped = config_switcher(old_cropped, nb_lines, nb_cols, coords_1=coords_old, coords_2=coords_new)
        new_image = cropped_to_img(new_cropped, nb_lines, nb_cols)
        plt.imshow(new_image)
        plt.xticks(xticks_location, range(nb_cols))
        plt.yticks(yticks_location, range(nb_lines))
        plt.title('New image')

        return

    save_button = widgets.Button(
        description='Save',
    )

    @save_button.on_click
    def save_on_click(b=None):
        global new_image

        filename = time.strftime('%d-%m-%Y_%H%M%S', time.localtime()) + '.png'
        filepath = os.path.join('outputs', filename)

        try:
            new_image.save(filepath)
            print('File successfully saved.')
        except:
            print('Error saving file.')

        return

    # --------- Main ---------
    list_buttons = [apply_button, save_button]
    box_buttons = widgets.HBox(children=list_buttons)

    box_final = widgets.VBox(children=[box_coords, box_buttons])

    return box_final
```

```python
launch_widget(cropped, nb_lines, nb_cols)
```

## Résolution

```python
solve_backtracking(cropped, nb_lines, nb_cols)
```

```python

```


```python
from ga import Ga, half, zero, one
import mv
import metric
from printer import Format, GaLatexPrinter
from sympy import Symbol, symbols, factor, collect, cos, sin, pi, srepr, sqrt, atan2
import numpy as np
Format()

g = '1 0 0 0 0, 0 1 0 0 0, 0 0 1 0 0, 0 0 0 0 -1, 0 0 0 -1 0'
(_1, _2, _3, _o, _i) = coords = symbols('1,2,3,o,\infty',real=True)

c3d = Ga('e_1 e_2 e_3 n_o n_\infty',g=g,coords=coords)
(e1, e2, e3, no, ni) = c3d.mv()
(r,th,phi,alpha,beta,gamma) = symbols('r theta phi alpha beta gamma',real=True)
```

```python
def make_euclidean_vector(a, n=3, ga=None):
    if isinstance(a,str):
        v = zero
        symbols_list = []
        for i in range(n):
            a_i = Symbol(a+str(i+1))
            symbols_list.append(a_i*ga.basis[i])
            v += a_i*ga.basis[i]
        v = ga.mv(v)
        return v, symbols_list
```

```python
t,_ = make_euclidean_vector('t',ga=c3d)
```

```python
translator = one - half * t * ni
translator * no * translator.rev()
```

\begin{equation*} t_{1} \boldsymbol{e}_{1} + t_{2} \boldsymbol{e}_{2} + t_{3} \boldsymbol{e}_{3} + \boldsymbol{n}_{o} + \left ( \frac{1}{2} {\left ( t_{1} \right )}^{2} + \frac{1}{2} {\left ( t_{2} \right )}^{2} + \frac{1}{2} {\left ( t_{3} \right )}^{2}\right ) \boldsymbol{n}_{\infty} \end{equation*}

```python
from sympy.abc import x, theta
# Define unit bivectors
e12 = e1 ^ e2
e13 = e1 ^ e3
e23 = e2 ^ e3
e123 = e1 ^ e2 ^ e3
(B12, B13, B23) = symbols('B_12,B_13,B_23')
rotation_plane = ( B12 * e12 + B13 * e13 + B23 * e23 )
B = rotation_plane
rotor = cos(half * theta) - sin( half * theta) * rotation_plane
rotor
```

\begin{equation*} \cos{\left (\frac{\theta }{2} \right )}  - B_{12} \sin{\left (\frac{\theta }{2} \right )} \boldsymbol{e}_{1}\wedge \boldsymbol{e}_{2} - B_{13} \sin{\left (\frac{\theta }{2} \right )} \boldsymbol{e}_{1}\wedge \boldsymbol{e}_{3} - B_{23} \sin{\left (\frac{\theta }{2} \right )} \boldsymbol{e}_{2}\wedge \boldsymbol{e}_{3} \end{equation*}

```python
t = 2 * e2 + e3
B = e1*e2
th4 = half * half * pi
T = (one - half * t * ni)
R = (cos(th4) - sin(th4) * B)
M = T * R
```

```python
M
```

\begin{equation*} \frac{\sqrt{2}}{2}  - \frac{\sqrt{2}}{2} \boldsymbol{e}_{1}\wedge \boldsymbol{e}_{2} - \frac{\sqrt{2}}{2} \boldsymbol{e}_{1}\wedge \boldsymbol{n}_{\infty} - \frac{\sqrt{2}}{2} \boldsymbol{e}_{2}\wedge \boldsymbol{n}_{\infty} - \frac{\sqrt{2}}{4} \boldsymbol{e}_{3}\wedge \boldsymbol{n}_{\infty} + \frac{\sqrt{2}}{4} \boldsymbol{e}_{1}\wedge \boldsymbol{e}_{2}\wedge \boldsymbol{e}_{3}\wedge \boldsymbol{n}_{\infty} \end{equation*}

```python
w = (t ^ B) * B.inv()
w
```

\begin{equation*}  \boldsymbol{e}_{3} \end{equation*}

```python
v = (one - R * R).inv() * (t < B)*B.inv()
v
```

\begin{equation*} - \boldsymbol{e}_{1} + \boldsymbol{e}_{2} \end{equation*}

```python
M_ = cos(th4) - sin(th4)*B - half * cos(th4) * t * ni + half * sin(th4) * t * B * ni
M_ == M
```

    True

```python
(one - R * R).inv()
```

\begin{equation*} \frac{1}{2}  - \frac{1}{2} \boldsymbol{e}_{1}\wedge \boldsymbol{e}_{2} \end{equation*}

```python
t < B
```

\begin{equation*} -2 \boldsymbol{e}_{1} \end{equation*}

```python
B.inv()
```

\begin{equation*} - \boldsymbol{e}_{1}\wedge \boldsymbol{e}_{2} \end{equation*}

# Rotor estimation computational graph

```python
a,_ = make_euclidean_vector('a',ga=c3d)
B = rotation_plane
a
```

\begin{equation*} a_{1} \boldsymbol{e}_{1} + a_{2} \boldsymbol{e}_{2} + a_{3} \boldsymbol{e}_{3} \end{equation*}

```python
(R0, R1, R2, R3) = symbols('R_0,R_1,R_2,R_3')
rotor = R0 - (R1*e1^e2) -(R2*e1^e3) - (R3*e2^e3)
# rotor = R0 - (R1*e2^e3) -(R2*e3^e1) - (R3*e1^e2)
rotor
```

\begin{equation*} R_{0}  - R_{1} \boldsymbol{e}_{1}\wedge \boldsymbol{e}_{2} - R_{2} \boldsymbol{e}_{1}\wedge \boldsymbol{e}_{3} - R_{3} \boldsymbol{e}_{2}\wedge \boldsymbol{e}_{3} \end{equation*}

```python
b = rotor * a  * rotor.rev()
b
```

\begin{equation*} \left ( {\left ( R_{0} \right )}^{2} a_{1} - 2 R_{0} R_{1} a_{2} - 2 R_{0} R_{2} a_{3} - {\left ( R_{1} \right )}^{2} a_{1} + 2 R_{1} R_{3} a_{3} - {\left ( R_{2} \right )}^{2} a_{1} - 2 R_{2} R_{3} a_{2} + {\left ( R_{3} \right )}^{2} a_{1}\right ) \boldsymbol{e}_{1} + \left ( {\left ( R_{0} \right )}^{2} a_{2} + 2 R_{0} R_{1} a_{1} - 2 R_{0} R_{3} a_{3} - {\left ( R_{1} \right )}^{2} a_{2} - 2 R_{1} R_{2} a_{3} + {\left ( R_{2} \right )}^{2} a_{2} - 2 R_{2} R_{3} a_{1} - {\left ( R_{3} \right )}^{2} a_{2}\right ) \boldsymbol{e}_{2} + \left ( {\left ( R_{0} \right )}^{2} a_{3} + 2 R_{0} R_{2} a_{1} + 2 R_{0} R_{3} a_{2} + {\left ( R_{1} \right )}^{2} a_{3} - 2 R_{1} R_{2} a_{2} + 2 R_{1} R_{3} a_{1} - {\left ( R_{2} \right )}^{2} a_{3} - {\left ( R_{3} \right )}^{2} a_{3}\right ) \boldsymbol{e}_{3} \end{equation*}

```python
rm = np.array([[r0**2 -r1**2 - r2**2 + r3**2, 2*(-r0*r1 - r2*r3), 2*(-r0*r2 + r1*r3)],
               [2*(r0*r1 - r2*r3), r0**2 -r1**2 + r2**2 - r3**2, 2*(-r0*r3 - r1*r2) ],
               [2*(r0*r2 + r1*r3), 2*(r0*r3 - r1*r2), r0**2 + r1**2 - r2**2 - r3**2  ]])
```

```python
th = half * theta
b_ = (cos(th))**2 * a + cos(th)*sin(th)*a*B - cos(th)*sin(th)*B*a - ((sin(th))**2) * B*a*B
```

```python
b_1 = (cos(th))**2 * a + 2 * cos(th)*sin(th)*(a < B) - ((sin(th))**2) * B*a*B
b_1 == b
```

    False

```python
rotor * a
```

\begin{equation*} \left ( a_{1} \cos{\left (\frac{\theta }{2} \right )} + \left(- B_{12} a_{2} - B_{13} a_{3}\right) \sin{\left (\frac{\theta }{2} \right )}\right ) \boldsymbol{e}_{1} + \left ( a_{2} \cos{\left (\frac{\theta }{2} \right )} + \left(B_{12} a_{1} - B_{23} a_{3}\right) \sin{\left (\frac{\theta }{2} \right )}\right ) \boldsymbol{e}_{2} + \left ( a_{3} \cos{\left (\frac{\theta }{2} \right )} + \left(B_{13} a_{1} + B_{23} a_{2}\right) \sin{\left (\frac{\theta }{2} \right )}\right ) \boldsymbol{e}_{3} + \left(- B_{12} a_{3} + B_{13} a_{2} - B_{23} a_{1}\right) \sin{\left (\frac{\theta }{2} \right )} \boldsymbol{e}_{1}\wedge \boldsymbol{e}_{2}\wedge \boldsymbol{e}_{3} \end{equation*}

```python
B*a*B
```

\begin{equation*} \left ( {\left ( B_{12} \right )}^{2} a_{1} - 2 B_{12} B_{23} a_{3} + {\left ( B_{13} \right )}^{2} a_{1} + 2 B_{13} B_{23} a_{2} - {\left ( B_{23} \right )}^{2} a_{1}\right ) \boldsymbol{e}_{1} + \left ( {\left ( B_{12} \right )}^{2} a_{2} + 2 B_{12} B_{13} a_{3} - {\left ( B_{13} \right )}^{2} a_{2} + 2 B_{13} B_{23} a_{1} + {\left ( B_{23} \right )}^{2} a_{2}\right ) \boldsymbol{e}_{2} + \left ( - {\left ( B_{12} \right )}^{2} a_{3} + 2 B_{12} B_{13} a_{2} - 2 B_{12} B_{23} a_{1} + {\left ( B_{13} \right )}^{2} a_{3} + {\left ( B_{23} \right )}^{2} a_{3}\right ) \boldsymbol{e}_{3} \end{equation*}

```python
B * a
```

\begin{equation*} \left ( B_{12} a_{2} + B_{13} a_{3}\right ) \boldsymbol{e}_{1} + \left ( - B_{12} a_{1} + B_{23} a_{3}\right ) \boldsymbol{e}_{2} + \left ( - B_{13} a_{1} - B_{23} a_{2}\right ) \boldsymbol{e}_{3} + \left ( B_{12} a_{3} - B_{13} a_{2} + B_{23} a_{1}\right ) \boldsymbol{e}_{1}\wedge \boldsymbol{e}_{2}\wedge \boldsymbol{e}_{3} \end{equation*}

```python
B | a
```

\begin{equation*} \left ( B_{12} a_{2} + B_{13} a_{3}\right ) \boldsymbol{e}_{1} + \left ( - B_{12} a_{1} + B_{23} a_{3}\right ) \boldsymbol{e}_{2} + \left ( - B_{13} a_{1} - B_{23} a_{2}\right ) \boldsymbol{e}_{3} \end{equation*}

```python
B < a
```

\begin{equation*} 0
 \end{equation*}

```python
a < B
```

\begin{equation*} \left ( - B_{12} a_{2} - B_{13} a_{3}\right ) \boldsymbol{e}_{1} + \left ( B_{12} a_{1} - B_{23} a_{3}\right ) \boldsymbol{e}_{2} + \left ( B_{13} a_{1} + B_{23} a_{2}\right ) \boldsymbol{e}_{3} \end{equation*}

```python
(-one) * (a < B)
```

\begin{equation*} \left ( B_{12} a_{2} + B_{13} a_{3}\right ) \boldsymbol{e}_{1} + \left ( - B_{12} a_{1} + B_{23} a_{3}\right ) \boldsymbol{e}_{2} + \left ( - B_{13} a_{1} - B_{23} a_{2}\right ) \boldsymbol{e}_{3} \end{equation*}

```python
B * B
```

\begin{equation*} - {\left ( B_{12} \right )}^{2} - {\left ( B_{13} \right )}^{2} - {\left ( B_{23} \right )}^{2} \end{equation*}

```python
a + cos(th)*sin(th)*(a < B)
```

\begin{equation*} \left ( a_{1} + \left(- \frac{B_{12} a_{2}}{2} - \frac{B_{13} a_{3}}{2}\right) \sin{\left (\theta  \right )}\right ) \boldsymbol{e}_{1} + \left ( a_{2} + \left(\frac{B_{12} a_{1}}{2} - \frac{B_{23} a_{3}}{2}\right) \sin{\left (\theta  \right )}\right ) \boldsymbol{e}_{2} + \left ( a_{3} + \left(\frac{B_{13} a_{1}}{2} + \frac{B_{23} a_{2}}{2}\right) \sin{\left (\theta  \right )}\right ) \boldsymbol{e}_{3} \end{equation*}

```python
av = e1 + e3
Bv = e1 ^ e2
th = pi/4
```

```python
th
```

    pi/4

```python
av + cos(th)*sin(th)*(av < Bv)
```

\begin{equation*}  \boldsymbol{e}_{1} + \frac{1}{2} \boldsymbol{e}_{2} + \boldsymbol{e}_{3} \end{equation*}

```python
(cos(th))**2 * av + 2 * cos(th)*sin(th)*(av < Bv) - ((sin(th))**2) * Bv*av*Bv
```

\begin{equation*}  \boldsymbol{e}_{2} + \boldsymbol{e}_{3} \end{equation*}

```python
(cos(th))**2 * av + 2 * cos(th)*sin(th)*(av < Bv) + ((sin(th))**2) * av*Bv*Bv
```

\begin{equation*}  \boldsymbol{e}_{2} \end{equation*}

```python
Bv * av
```

\begin{equation*} - \boldsymbol{e}_{2} + \boldsymbol{e}_{1}\wedge \boldsymbol{e}_{2}\wedge \boldsymbol{e}_{3} \end{equation*}

```python
Bv * av * Bv
```

\begin{equation*}  \boldsymbol{e}_{1} - \boldsymbol{e}_{3} \end{equation*}

```python
r2 = cos(pi/4) - sin(pi/4)*(e1 ^ e2)
r2
```

\begin{equation*} \frac{\sqrt{2}}{2}  - \frac{\sqrt{2}}{2} \boldsymbol{e}_{1}\wedge \boldsymbol{e}_{2} \end{equation*}

```python
r0 = np.cos(np.pi/4)
r1 = +np.sin(np.pi/4)
r2 = 0.0
r3 = 0.0
```

```python
rm = np.array([[r0**2 -r1**2 - r2**2 + r3**2, 2*(-r0*r1 - r2*r3), 2*(-r0*r2 + r1*r3)],
               [2*(r0*r1 - r2*r3), r0**2 -r1**2 + r2**2 - r3**2, 2*(-r0*r3 - r1*r2) ],
               [2*(r0*r2 + r1*r3), 2*(r0*r3 - r1*r2), r0**2 + r1**2 - r2**2 - r3**2  ]])
# rm = -1 * rm
rm
```

    array([[  2.22044605e-16,  -1.00000000e+00,   0.00000000e+00],
           [  1.00000000e+00,   2.22044605e-16,  -0.00000000e+00],
           [  0.00000000e+00,   0.00000000e+00,   1.00000000e+00]])

```python
np.dot(rm,np.array([1.0,0.0,0.0]).reshape(3,1))
```

    array([[ -2.22044605e-16],
           [  1.00000000e+00],
           [ -0.00000000e+00]])

```python
quaternion_matrix([-r3, r2, -r1, r0])
```

    array([[ 0., -1.,  0.,  0.],
           [ 1.,  0.,  0.,  0.],
           [-0.,  0.,  1.,  0.],
           [ 0.,  0.,  0.,  1.]])

```python
from transformations import quaternion_matrix
```

```python
np.dot(quaternion_matrix([-r3, r2, -r1, r0]),np.array([1.0,0.0,0.0,1.0]).reshape(4,1))[:3]
```

    array([[ 0.],
           [ 1.],
           [ 0.]])

```python
quaternion_matrix?
```

```python
cos(0.123/ 2)
# sin(0.123/ 2)
```

    0.998109470983818