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)) # st.table(df_styler) # st.dataframe(df_styler) html = df_styler.to_html(escape=False, index=False) # # st.text(html) 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!')