-
Notifications
You must be signed in to change notification settings - Fork 0
/
display_sat_results.py
141 lines (127 loc) · 5.78 KB
/
display_sat_results.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!venv/bin/python
from sys import argv, stdin, stderr
from lib.file_io import read_grid
def interpret_results(clause, gridWidth, gridHeight):
"""
Affiche dans la ligne de commade une grille de Dosum Fuwari résolue sous
forme textuelle à partir de la clause fournie par le satsolver.
Arguments:
- clause: variables rendues par le satsolver définissant les positions
des cases noires, des ballons et des pierres.
Format attendu: liste d'entiers. Ex: [-1, 2, -3,...]
Symboles utilisés pour l'affichage:
- 'B' = ballon
- 'S' = pierre (stone)
- 'N' = case noire
- '-' = case vide
"""
# Parcourir la clause en ignorant les variables en dehors de la grille
# servant uniquement pour résoudre le problème
x = 0 # colonne courante
y = 0 # ligne courante
# La première variable dans la grille (la case en haut à gauche) est
# précédée par une ligne entière de variables
i = gridWidth * 3
# On ne sait pas combien de variables le satsolver a rajouté dans la
# clause pour résoudre le problème, on doit donc compter les lignes pour
# savoir où s'arrêter
while y < gridHeight:
if clause[i] > 0:
# Afficher un ballon
print("B", end=" ")
elif clause[i + 1] > 0:
# afficher une pierre
print("S", end=" ")
elif clause[i + 2] > 0:
# afficher une case noire
print("N", end=" ")
else:
# afficher une case vide
print("-", end=" ")
i += 3 # passer au groupe de variables suivante
x += 1 # passer à la colonne suivante
if x >= gridWidth:
# si on est arrivé en bout de ligne, afficher un retour à ligne
print("")
# repasser à la premièrecolonne et passer à la ligne suivante
x = 0
y += 1
# terminer l'affichage par une ligne pour bien marquer que c'est la fin de la grille
print(
"________________________________________________________________________________\n"
)
if __name__ == "__main__":
if len(argv) < 3:
print("Error: incorrect number of arguments", file=stderr)
print(
"Usage: {} <name of satsolver> path/to/grid/file path/to/sat/output/file".format(
argv[0]
),
file=stderr,
)
print("Supported satsolvers: minisat, picosat", file=stderr)
print("Sat output can be read from stdin", file=stderr)
exit(1)
# Lire la grille
grid = read_grid(argv[2])
# Ouvrir le fichier sat
if len(argv) == 3:
satfile = stdin
else:
satfile = open(argv[3], "r")
content = satfile.read() # Lire le contenu
# Fermer le fichier
if len(argv) > 2:
satfile.close()
# Parser le contenu
if argv[1] == "minisat":
# Minisat ne fournit qu'une solution à la fois, et le format de fichier est très simple:
# La première ligne contient "SAT\n" si le problème est satisfaisable, et la 2e ligne
# contient la solution
satisfiability = content.split("\n", 1)[0]
solutions = content.split("\n", 1)[1]
if satisfiability == "SAT":
solutions = solutions.split("\n")
# se débarasser de potentielles listes vides causées par le split qui agit en fin de ligne
solutions = [line for line in solutions if line != ""]
# convertir la solution (chaine de caractères) en liste d'entiers
solutions = [list(map(int, line.split(" "))) for line in solutions]
print("S : stone\nB : balloon\nN : black cell\n- : empty cell\n")
print("{} solutions found:".format(len(solutions)))
else:
print("No solutions found")
exit(0)
elif argv[1] == "picosat":
# l'affichage de sortie de picosat est plus compliqué: si le problème est satisfaisable
# la 1e ligne contiendra "s SATISFIABLE\n". Les lignes suivantes contiennent alors une
# solution au problème, avec un renvoi à la ligne automatique à 79 caractères, avec chaque
# ligne préfixée par "v ". De plus chaque solution trouvée est précédée par la même ligne
# "s SATISFIABLE\n". Et en plus si plusieurs solutions ont été trouvées la dernière ligne
# du fichier contiendra le nombre de solutions "s SOLUTIONS ..." avec ... le nombre de
# solutions
satisfiability = content.split("\n", 1)[0] # récupérer la 1e ligne
if satisfiability == "s SATISFIABLE":
# supprimer les lignes qui séparent les solutions
solutions = content.replace("s SATISFIABLE\n", "")
solutions = solutions.split("s SOLUTIONS ", 1)[
0
] # se débarasser du nombre de solutions
solutions = solutions.replace(
"v ", ""
) # supprimer tous les "v " en début de ligne
solutions = solutions.replace(
"\n", " "
) # recoller toutes les lignes ensemble
solutions = solutions.split(" 0 ") # couper la liste à chaque 0
# se débarasser de potentielles listes vides causées par le split qui agit en fin de ligne
solutions = [line for line in solutions if line != ""]
# convertir la solution (chaine de caractères) en liste d'entiers
solutions = [list(map(int, line.split(" "))) for line in solutions]
print("S : stone\nB : balloon\nN : black cell\n- : empty cell\n")
print("{} solutions found:".format(len(solutions)))
else:
print("No solutions found")
exit(0)
# Afficher les solutions
for line in solutions:
interpret_results(line, grid["width"], grid["height"])