|
import streamlit as st |
|
from sudoku.train import SudokuTrialErrorLightning, TrialEveryPosException |
|
from sudoku.helper import display_as_dataframe, get_grid_number_soluce |
|
import numpy as np |
|
import re |
|
import torch |
|
|
|
model = SudokuTrialErrorLightning.load_from_checkpoint(checkpoint_path="model_9_m3_big_validation_th.ckpt") |
|
|
|
empty_grid = ''' |
|
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 | 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 | 0 0 0 |
|
0 0 0 | 0 0 0 | 0 0 0 |
|
0 0 0 | 0 0 0 | 0 0 0 |
|
''' |
|
grid_evil_0 = ''' |
|
[0,0,0, 1,6,0, 2,0,0], |
|
[0,3,0, 0,0,5, 0,0,4], |
|
[0,0,7, 0,0,0, 0,9,0], |
|
|
|
[0,0,1, 0,0,0, 0,8,2], |
|
[3,0,0, 7,0,4, 0,0,5], |
|
[4,2,0, 0,0,0, 6,0,0], |
|
|
|
[0,8,0, 0,0,0, 5,0,0], |
|
[7,0,0, 8,0,0, 0,2,0], |
|
[0,0,6, 0,5,1, 0,0,0], |
|
''' |
|
grid_evil_1 = ''' |
|
[0,0,0, 2,0,0, 0,0,0], |
|
[0,0,9, 7,0,0, 3,8,0], |
|
[3,6,0, 0,0,0, 0,7,0], |
|
|
|
[1,0,6, 8,0,0, 0,0,0], |
|
[0,0,0, 3,5,9, 0,0,0], |
|
[0,0,0, 0,0,2, 8,0,5], |
|
|
|
[0,4,0, 0,0,0, 0,9,1], |
|
[0,2,5, 0,0,8, 7,0,0], |
|
[0,0,0, 0,0,6, 0,0,0], |
|
] |
|
''' |
|
grid_evil_2 = ''' |
|
[0,2,0, 1,0,0, 0,7,0], |
|
[0,0,0, 3,0,2, 0,0,0], |
|
[0,0,1, 0,8,0, 0,4,0], |
|
|
|
[9,0,0, 0,1,0, 0,0,7], |
|
[0,0,8, 0,6,0, 0,5,0], |
|
[0,0,0, 0,0,0, 0,0,0], |
|
|
|
[0,8,0, 0,3,6, 0,0,9], |
|
[0,0,5, 0,7,0, 0,0,6], |
|
[0,0,2, 0,0,0, 0,0,3], |
|
] |
|
''' |
|
grids = { |
|
'empty': empty_grid, |
|
'evil_1': grid_evil_0, |
|
'evil_2': grid_evil_1, |
|
'evil_3': grid_evil_2 |
|
} |
|
|
|
def str_to_row_col_grid(su_str): |
|
su_str = re.sub(r'[^\d.]', '', su_str).replace('.','0') |
|
|
|
assert len(su_str)==81 |
|
return [[int(su_str[j*9+i]) for i in range(9)] for j in range(9)] |
|
|
|
def build_tensor_out_of_grid(grid): |
|
np_grid = np.asarray(grid) |
|
big_grid = np.zeros((1,2,9,9,9), dtype=np.float32) |
|
for i in range(9): |
|
big_grid[0,1,:,:,i] = (np_grid==i+1) |
|
big_grid[0,0,:,:,i] = ((np_grid!=i+1) & (np_grid!=0)) |
|
return torch.from_numpy(big_grid).view(1,2,729) |
|
|
|
def build_grid_and_display(str_grid): |
|
test_x = build_tensor_out_of_grid(str_grid) |
|
return test_x, display_as_dataframe(test_x) |
|
st.markdown('# Deep learning sudoku Solver') |
|
st.markdown('''### Author: Sébastien Guissart |
|
|
|
Detailed method in this [paper](https://huggingface.co/spaces/SebastienGuissart/deeplearning_sudoku_solver/blob/main/100%25%20accurate%20Sudoku%20solving%20with%20deep%20learning%20algorithm.pdf) |
|
''') |
|
|
|
option = st.selectbox( |
|
"select template grids", |
|
grids, |
|
) |
|
x = st.text_area('You can edit the grid, every format is accepted. Empty cell can be designed by `0` or by `.`', value=grids[option], height=300) |
|
|
|
st.markdown('### Initial grid') |
|
tensor_grid, df_styler = build_grid_and_display(str_to_row_col_grid(x)) |
|
|
|
|
|
html = df_styler.to_html(escape=False, index=False) |
|
|
|
st.html(html) |
|
st.markdown(''' |
|
## Checking the number of solutions |
|
(with classical backtracking algorithm). |
|
|
|
Number of solutions must be one to trigger the grid resolution. |
|
''') |
|
n_sol = get_grid_number_soluce(str_to_row_col_grid(x)) |
|
|
|
st.markdown(f"number of solution: {'>2' if n_sol==2 else n_sol}") |
|
if n_sol==1: |
|
st.markdown('## Predicting grid step by step') |
|
new_X = model.predict(tensor_grid) |
|
X_sum= new_X.sum() |
|
st.html(display_as_dataframe(new_X).to_html(escape=False, index=False)) |
|
i=1 |
|
while new_X.sum()<729: |
|
i+=1 |
|
st.markdown(f'iteration {i}') |
|
try: |
|
new_X = model.predict(new_X, func_text_display=st.markdown) |
|
except TrialEveryPosException: |
|
st.markdown('''## The grid is super evil! |
|
please share it as A Discussion in the `Community` tab. |
|
Except if it is this one: https://www.telegraph.co.uk/news/science/science-news/9359579/Worlds-hardest-sudoku-can-you-crack-it.html |
|
|
|
Using trail error model enhanced by backtracking |
|
''') |
|
is_valid, new_X = model.backtracking_predict( |
|
new_X, |
|
func_text_display=st.markdown, |
|
func_tensor_display=lambda t: st.html(display_as_dataframe(t).to_html(escape=False, index=False)), |
|
) |
|
assert is_valid |
|
st.html(display_as_dataframe(new_X).to_html(escape=False, index=False)) |
|
new_X_sum = new_X.sum() |
|
assert new_X_sum> X_sum |
|
X_sum = new_X_sum |
|
st.markdown('## Grid solved!') |
|
|
|
|
|
|