def insert_stench_regle(gs: Gophersat, wumpus_voca: List, stench_voca: List): for stench in stench_voca: # Soit le symbole Wij ij = stench[1:] # On enleve la lettre i = int(ij[:2]) # On prend les deux premiers chiffres pour l'indice i j = int(ij[2:]) # On prend les deux derniers chiffres pour l'indice j i_moins_1 = int_to_two_digits_str(i, -1) i_plus_1 = int_to_two_digits_str(i, 1) j_moins_1 = int_to_two_digits_str(j, -1) j_plus_1 = int_to_two_digits_str(j, 1) i = int_to_two_digits_str(i) j = int_to_two_digits_str(j) wumpuses = [] if f"W{i_plus_1}{j}" in wumpus_voca: wumpuses.append(f"W{i_plus_1}{j}") if f"W{i_moins_1}{j}" in wumpus_voca: wumpuses.append(f"W{i_moins_1}{j}") if f"W{i}{j_plus_1}" in wumpus_voca: wumpuses.append(f"W{i}{j_plus_1}") if f"W{i}{j_moins_1}" in wumpus_voca: wumpuses.append(f"W{i}{j_moins_1}") clause = wumpuses + [f"-{stench}"] gs.push_pretty_clause(clause)
def push_clause_from_wumpus(gs: Gophersat, case_contents: str, position: Tuple[str, str], is_from_know_method: bool = False, enable_log: bool = False): if enable_log: print(f"contents is : {case_contents}") facts = [] for case_content in case_contents: if enable_log: print(f"inserting from wumpus : {case_content}\n") tmp_facts = wumpus_to_clause(case_content, position) if tmp_facts == -1: print("Error : Invalid case contents : wumpus to clause") return -1 else: facts = facts + tmp_facts if is_from_know_method == False: # Si on utilise pas la methode know, on est certains de ce qu'il n'y a pas dans la case facts = facts + get_implicit_negative_facts(facts, position) for fact in facts: # On doit inserer les clauses une a une gs.push_pretty_clause([fact])
def insert_trou_regle(gs: Gophersat, trou_voca: List, brise_voca: List): for trou in trou_voca: # Soit le symbole Tij, une chaine de caractere avec i et j appartient a [0..99] # On enleve la lettre et on recupere i et j ij = trou[1:] i = int(ij[:2]) # On prend les deux premiers chiffres pour l'indice i j = int(ij[2:]) # On prend les deux derniers chiffres pour l'indice j i_moins_1 = int_to_two_digits_str(i, -1) i_plus_1 = int_to_two_digits_str(i, 1) j_moins_1 = int_to_two_digits_str(j, -1) j_plus_1 = int_to_two_digits_str(j, 1) i = int_to_two_digits_str(i) j = int_to_two_digits_str(j) brises = [] if f"B{i_plus_1}{j}" in brise_voca: brises.append(f"B{i_plus_1}{j}") if f"B{i_moins_1}{j}" in brise_voca: brises.append(f"B{i_moins_1}{j}") if f"B{i}{j_plus_1}" in brise_voca: brises.append(f"B{i}{j_plus_1}") if f"B{i}{j_moins_1}" in brise_voca: brises.append(f"B{i}{j_moins_1}") for brise in brises: gs.push_pretty_clause([f"-{trou}", brise])
def insert_wumpus_stench_regle(gs: Gophersat, wumpus_voca: List, stench_voca: List): for wumpus in wumpus_voca: # Soit le symbole Tij ij = wumpus[1:] # On enleve la lettre i = int(ij[:2]) # On prend les deux premiers chiffres pour l'indice i j = int(ij[2:]) # On prend les deux derniers chiffres pour l'indice j i_moins_1 = int_to_two_digits_str(i, -1) i_plus_1 = int_to_two_digits_str(i, 1) j_moins_1 = int_to_two_digits_str(j, -1) j_plus_1 = int_to_two_digits_str(j, 1) i = int_to_two_digits_str(i) j = int_to_two_digits_str(j) stenches = [] if f"S{i_plus_1}{j}" in stench_voca: stenches.append(f"S{i_plus_1}{j}") if f"S{i_moins_1}{j}" in stench_voca: stenches.append(f"S{i_moins_1}{j}") if f"S{i}{j_plus_1}" in stench_voca: stenches.append(f"S{i}{j_plus_1}") if f"S{i}{j_moins_1}" in stench_voca: stenches.append(f"S{i}{j_moins_1}") for stench in stenches: gs.push_pretty_clause([f"-{wumpus}", stench])
def is_number_possible(gs: Gophersat, number_to_insert: int, i: int, j: int): gs.push_pretty_clause([f"{number_to_insert}_{i}_{j}"]) solvable = gs.solve() if not solvable: gs.pop_clause() return solvable
def insert_only_one_wumpus_regle(gs: Gophersat, wumpus_voca: List): wumpus_voca2 = wumpus_voca.copy() for case in wumpus_voca: wumpus_voca2.remove(case) for c in wumpus_voca2: gs.push_pretty_clause([f"-{case}", f"-{c}"]) gs.push_pretty_clause(wumpus_voca)
def insert_une_menace_par_case_regle(gs: Gophersat, wumpus_voca: List, trou_voca: List): trou_voca_pile = trou_voca.copy() wumpus_voca_pile = wumpus_voca.copy() for i in range(len(wumpus_voca)): trou = trou_voca_pile.pop() wumpus = wumpus_voca_pile.pop() gs.push_pretty_clause([f"-{wumpus}", f"-{trou}"]) gs.push_pretty_clause([f"-{trou}", f"-{wumpus}"])
def initialisation(N, random = False): ww = WumpusWorld(N, random) voc = creationVoc(ww.get_n()) gs = Gophersat(gophersat_exec, voc) #état des lieux 1: on ne sait rien knowledge = [[]] * N for i in range(N): knowledge[i] = [''] * N for j in range(N): ajoutClauseEmpty(gs, i, j) ajoutClausesBreeze(gs, i, j) ajoutClausesStench(gs, i, j) ajoutClausesWumpus(gs, i, j) ajoutClausesPuit(gs, i, j) #on probe l'unique case safe probe1=ww.probe(0, 0) knowledge[0][0] = probe1[1] if ('.' in probe1[1]): #la case est empty gs.push_pretty_clause(["E0_0"]) if ('B' in probe1[1]): #la case est breeze gs.push_pretty_clause(["B0_0"]) if ('S' in probe1[1]): #la case est stenchy gs.push_pretty_clause(["S0_0"]) return(ww, gs, knowledge)
def initialisation(size, wwr): #ww = WumpusWorld(size, random) voc = creationVoc(size) gs = Gophersat(gophersat_exec, voc) #état des lieux 1: on ne sait rien knowledge = [[]] * size for i in range(size): knowledge[i] = [''] * size for j in range(size): ajoutClauseEmpty(gs, i, j) ajoutClausesBreeze(size, gs, i, j) ajoutClausesStench(size, gs, i, j) ajoutClausesWumpus(size, gs, i, j) ajoutClausesPuit(size, gs, i, j) #on probe l'unique case safe status, probe1, cost = wwr.probe(0, 0) knowledge[0][0] = probe1 if ('.' in probe1): #la case est empty gs.push_pretty_clause(["E0_0"]) if ('B' in probe1): #la case est breeze gs.push_pretty_clause(["B0_0"]) if ('S' in probe1): #la case est stenchy gs.push_pretty_clause(["S0_0"]) return (gs, knowledge)
def insert_only_one_number_in_case(gs: Gophersat, voca: List): for case in voca: num_case = int(case.split('_')[0]) i = case.split('_')[1] j = case.split('_')[2] ou_clause = [case] for number in range( 1, 10 ): # non(1_i_j) OU non(2_i_j) ET non(1_i_j) OU non(3_i_j) ET ... ET non(1_i_j) OU non(9_i_j) if num_case != number: ou_clause.append(f"{number}_{i}_{j}") gs.push_pretty_clause([f"-{case}", f"-{number}_{i}_{j}"]) gs.push_pretty_clause(ou_clause) ou_clause = []
def insert_one_value_in_row(gs: Gophersat, voca: List): for case in voca: num_case = case.split('_')[0] i = case.split('_')[1] j = int(case.split('_')[2]) ou_clause = [case] for j_prime in range( 0, 9 ): # non(1_i_j) OU non(1_i_0) ET non(1_i_j) OU non(1_i_1) ET ... ET non(1_i_j) OU non(1_i_8) if j != j_prime: ou_clause.append(f"{num_case}_{i}_{j_prime}") gs.push_pretty_clause( [f"-{case}", f"-{num_case}_{i}_{j_prime}"]) gs.push_pretty_clause(ou_clause) ou_clause = []
def insert_one_value_in_col(gs: Gophersat, voca: List): for case in voca: num_case = case.split('_')[0] i = int(case.split('_')[1]) j = case.split('_')[2] ou_clause = [case] for i_prime in range( 0, 9 ): # non(1_i_j) OU non(1_1_j) ET non(1_i_j) OU non(1_2_j) ET ... ET non(1_i_j) OU non(1_8_j) if i != i_prime: ou_clause.append(f"{num_case}_{i_prime}_{j}") gs.push_pretty_clause( [f"-{case}", f"-{num_case}_{i_prime}_{j}"]) gs.push_pretty_clause(ou_clause) ou_clause = []
def insert_one_value_in_square(gs: Gophersat, voca: List): for case in voca: num_case = case.split('_')[0] i = int(case.split('_')[1]) j = int(case.split('_')[2]) ib = 3 * (i // 3) # coordinates of the first case of the square jb = 3 * (j // 3) ou_clause = [case] for i_prime in range(ib, ib + 3): for j_prime in range(jb, jb + 3): if i != i_prime or j != j_prime: ou_clause.append(f"{num_case}_{i_prime}_{j_prime}") gs.push_pretty_clause( [f"-{case}", f"-{num_case}_{i_prime}_{j_prime}"]) gs.push_pretty_clause(ou_clause) ou_clause = []
def generate_sudoku() -> Tuple[List, List]: voc = generate_voca() gs = Gophersat(gophersat_exec, voc) insert_rules(gs, voc) soluce = generate_random_sudoku(gs) hidden_sudoku = hide_case_sudoku(0, soluce, gs) return (soluce, hidden_sudoku)
def hide_case_sudoku(difficulty: int, sudoku: List, gs: Gophersat): cpt = 0 already_visited = [] hidden_sudoku = copy.deepcopy(sudoku) while cpt < 15: i = random.randrange(0, 9) # On chope des coordonnées au hasard j = random.randrange(0, 9) if (i, j) not in already_visited: gs.remove_pretty_clause([f"{sudoku[i][j]}_{i}_{j}"]) gs.solve() hidden_sudoku[i][j] = ' ' already_visited.append((i, j)) cpt += 1 if not is_there_one_model(gs): print(f"Error : more than one model : {gs.count_model()}") else: return hidden_sudoku
def cartographier(wwr: WumpusWorldRemote, taille_grille: int = 4, enable_log: bool = False): wumpus_voca = generate_wumpus_voca(taille_grille) gold_voca = generate_gold_voca(taille_grille) stench_voca = generate_stench_voca(taille_grille) brise_voca = generate_brise_voca(taille_grille) trou_voca = generate_trou_voca(taille_grille) voc = wumpus_voca + gold_voca + stench_voca + brise_voca + trou_voca gs = Gophersat(gophersat_exec, voc) res = init_res(taille_grille) # On modelise les regles insert_all_regles(gs, wumpus_voca, trou_voca, brise_voca, stench_voca) if (gs.solve() and enable_log): print(f"vocabulaire inseré sans contradiction") print(wwr) elif (gs.solve() == False): print(f"contradiction dans le vocabulaire inseré") return -1 if (enable_log): print("\nBefore loop log :\n") print(f"{gs.solve()}") print(f"{gs.get_pretty_model()}") print("\n==========================\n") i_str = "" j_str = "" status, percepts, cost = wwr.probe(0, 0) print(status, percepts, cost) res[0][0] = percepts is_from_know_method = False push_clause_from_wumpus(gs, percepts, ["00", "00"], is_from_know_method, False) for i in range(taille_grille): for j in range(taille_grille): if i != 0 or j != 0: i_str = int_to_two_digits_str(i) j_str = int_to_two_digits_str(j) if is_wumpus_possible(gs, [i_str, j_str]): if is_wumpus_mandatory(gs, [i_str, j_str], wumpus_voca): status, percepts, cost = wwr.know_wumpus(i, j) if percepts == "Correct wumpus position.": percepts = "W" is_from_know_method = True else: status, percepts, cost = wwr.cautious_probe(i, j) elif is_trou_possible(gs, [i_str, j_str]): if is_trou_mandatory(gs, [i_str, j_str], trou_voca, res, taille_grille): status, percepts, cost = wwr.know_pit(i, j) if percepts == "Correct pit position.": percepts = "P" is_from_know_method = True else: status, percepts, cost = wwr.cautious_probe(i, j) else: status, percepts, cost = wwr.probe(i, j) if enable_log: print(status, percepts, cost, i, j) res[i][j] = percepts if ( push_clause_from_wumpus(gs, percepts, [i_str, j_str], is_from_know_method, False) == -1 ): # Si erreur lors de l'insertion de clauses on arrete tout : on fausse le modele gs.solve() print(f"Modele :\n {gs.get_pretty_model()} \n ---") return -1 is_from_know_method = False if (enable_log): print_case_contents_post_insertion(i, j, percepts, wwr, gs.solve()) if (gs.solve() == False): return -1 if (enable_log): print("\n\n==========================") print(f"Satisfiabilité : {gs.solve()}") print(f"Modele trouvé :\n {gs.get_pretty_model()} \n ---") return res
def insert_safety_regle(gs: Gophersat): gs.push_pretty_clause(["-W0000"]) gs.push_pretty_clause(["-T0000"])
def insert_brise_regle(gs: Gophersat, brise_voca: List, trou_voca: List): #-Bij ou T(i-1)j ou T(i+1)j ou Ti(j-1) ou Ti(j+1) for brise in brise_voca: # Soit le symbole Bij # On enleve la lettre et on recupere i et j ij = brise[1:] i = int(ij[:2]) # On prend les deux premiers chiffres pour l'indice i j = int(ij[2:]) # On prend les deux derniers chiffres pour l'indice j i_moins_1 = int_to_two_digits_str(i, -1) i_plus_1 = int_to_two_digits_str(i, 1) j_moins_1 = int_to_two_digits_str(j, -1) j_plus_1 = int_to_two_digits_str(j, 1) i = int_to_two_digits_str(i) j = int_to_two_digits_str(j) trous = [] if f"T{i_plus_1}{j}" in trou_voca: trous.append(f"T{i_plus_1}{j}") if f"T{i_moins_1}{j}" in trou_voca: trous.append(f"T{i_moins_1}{j}") if f"T{i}{j_plus_1}" in trou_voca: trous.append(f"T{i}{j_plus_1}") if f"T{i}{j_moins_1}" in trou_voca: trous.append(f"T{i}{j_moins_1}") clause = trous + [f"-{brise}"] gs.push_pretty_clause(clause) # -Tij ou B(i-1)j ou B(i+1)j ou Bi(j-1) ou Bi(j+1) for trou in trou_voca: # Soit le symbole Tij ij = trou[1:] # On eneleve la lettre i = int(ij[:2]) # On prend les deux premiers chiffres pour l'indice i j = int(ij[2:]) # On prend les deux derniers chiffres pour l'indice j i_moins_1 = int_to_two_digits_str(i, -1) i_plus_1 = int_to_two_digits_str(i, 1) j_moins_1 = int_to_two_digits_str(j, -1) j_plus_1 = int_to_two_digits_str(j, 1) i = int_to_two_digits_str(i) j = int_to_two_digits_str(j) brises = [] if f"B{i_plus_1}{j}" in brise_voca: brises.append(f"B{i_plus_1}{j}") if f"B{i_moins_1}{j}" in brise_voca: brises.append(f"B{i_moins_1}{j}") if f"B{i}{j_plus_1}" in brise_voca: brises.append(f"B{i}{j_plus_1}") if f"B{i}{j_moins_1}" in brise_voca: brises.append(f"B{i}{j_moins_1}") clause = brises + [f"-{trou}"] gs.push_pretty_clause(clause)
def is_there_one_model(gs: Gophersat): return gs.count_model() == 1