-
Notifications
You must be signed in to change notification settings - Fork 1
/
PandBox.py
295 lines (221 loc) · 12.8 KB
/
PandBox.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
import matplotlib
import matplotlib.pyplot as plt
from tkinter import *
from tkinter import ttk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from LogicalProblem import LogicalProblem
# Main function for he whole application
class Main_Application():
def __init__(self, master):
self.master = master
self.problems = []
self.valid = True
self.num_variables = StringVar()
self.num_variables.set('')
self.num_complexity = StringVar()
self.num_complexity.set('')
self.num_premises = StringVar()
self.num_premises.set('')
self.premise_figures = []
self.premise_subplots = []
self.premise_canvas = []
self.connector_canvas = []
self.initiate_gui() # Initate all the GUI elements
self.draw() # Draw all the GUI elements to the window
def generateProblem(self):
newProblem = LogicalProblem(int(self.variable_input.get()), int(self.premise_input.get()), int(self.complexity_input.get()), self.valid)
newProblem.generate_random()
self.problems.append(newProblem)
self.canvas.delete('all')
self.drawTree(-1)
self.premise_input = Spinbox(self.master, from_ = 0, to = newProblem.getNumPossiblePremises() - 1, font=('helvetica', 20))
self.premise_input.grid(column = 3, row = 1, columnspan= 1, padx = 10, pady=10)
def generatePremises(self):
if len(self.problems) == 0:
return
self.problems[-1].generatePremises(int(self.premise_input.get()))
self.drawPremises()
return
def drawPremises(self):
problem = self.problems[-1]
connectors = problem.getConnectors()
self.premise_figures = []
self.premise_subplots = []
self.forgetPremiseCanvas()
self.connector_canvas = []
for con in range(len(connectors)):
self.premise_figures.append(matplotlib.figure.Figure(figsize=(12,1), dpi = 100))
self.premise_subplots.append(self.premise_figures[-1].add_subplot(111))
self.connector_canvas.append(FigureCanvasTkAgg(self.premise_figures[-1], master = self.connector_frame))
self.connector_canvas[-1].get_tk_widget().grid(column = 0, row = 0 + con, columnspan=3, sticky = 'news')
self.premise_subplots[-1].get_xaxis().set_visible(False)
self.premise_subplots[-1].get_yaxis().set_visible(False)
latex_str= connectors[con].getLatexString()
latex_str = "$" + latex_str + "$"
if (con == len(connectors) - 1):
latex_str = 'Conclusion: ' + latex_str
self.premise_subplots[-1].clear()
self.premise_subplots[-1].text(0.05, 0.6, latex_str, fontsize = 14)
self.connector_canvas[-1].draw()
self.connector_frame.update_idletasks()
self.premise_canvas.config(scrollregion=self.premise_canvas.bbox("all"))
return
def forgetPremiseCanvas(self):
for can in self.connector_canvas:
for item in can.get_tk_widget().find_all():
can.get_tk_widget().delete(item)
def drawTree(self, problem_num):
problem = self.problems[problem_num]
tree = problem.getTree()
tree.organizeTree()
for i in range(tree.numLevels()):
for j in range(tree.levelSize(i)):
current_node = tree.getNode(i,j) # Just to say what the current node is
node_text = '{'
current_variables = current_node.getVariables()
for var in current_variables:
node_text += var.stringVar() + ','
if len(node_text) > 1:
node_text = node_text[:-1]
node_text += '}'
dw = 1200/(tree.levelSize(i))
self.canvas.create_text(dw*(1/2 + j), 100*(tree.numLevels() - i), text= node_text, fill = 'black', font = ("TkFixedFont", 14))
if not (current_node.child == -1):
child_dw = 1200/(tree.levelSize(i - 1))
self.canvas.create_line(dw*(1/2 + j),100*(tree.numLevels() - i) + 10,child_dw*(1/2 + current_node.child),100*(tree.numLevels() - i + 1) - 10, fill="black", width=3)
def swapValidity(self):
self.valid = not self.valid
if self.valid:
self.can_satisfy = Button(self.master, command = self.swapValidity, text = " ", bg = 'green', font=('helvetica', 16))
self.can_satisfy.grid(column=5, row=1, columnspan=1, pady=10)
else:
self.can_satisfy = Button(self.master, command = self.swapValidity, text = " ", bg = 'red', font=('helvetica', 16))
self.can_satisfy.grid(column=5, row=1, columnspan=1, pady=10)
# Function to force the complexity to be within a certain range depending on the number of variables
def updateComplexity(self, a, b, c):
var_input = int(self.variable_input.get()) # Get the current number of variables
n = 0 # This will be the minimum complexity
S = 1 # Just a dummy
while var_input >= S: # While the number of variables is less than 2^n we add 1 to n
n += 1
S = 2**n
# All of the crap in this if statement below is just to make sure the UI doesnt let you have non-possible complexity values for any given number of variables if you want non-valid answers
if not self.valid: # If we want a non-valid problem we can have less complexity
n = 1
self.num_complexity.set(str(n)) # This is just resetting the complexity gui element to add the new min max
self.complexity_input.grid_forget()
if (var_input == 1):
self.complexity_input = Spinbox(self.master, from_ = n, to = 1, textvariable=self.num_complexity, font=('helvetica', 20))
self.complexity_input.grid(column = 4, row = 1, columnspan= 1, padx = 10, pady=10)
else:
self.complexity_input = Spinbox(self.master, from_ = n, to = var_input - 1, textvariable=self.num_complexity, font=('helvetica', 20))
self.complexity_input.grid(column = 4, row = 1, columnspan= 1, padx = 10, pady=10)
return
# This works because at each n level in a tree you can have up to possibly 2^n variables and you can also have n variables you can also make n levels
self.num_complexity.set(str(n)) # This is just resetting the complexity gui element to add the new min max
self.complexity_input.grid_forget()
self.complexity_input = Spinbox(self.master, from_ = n, to = var_input, textvariable=self.num_complexity, font=('helvetica', 20))
self.complexity_input.grid(column = 4, row = 1, columnspan= 1, padx = 10, pady=10)
return
def _on_mousewheel(self, event):
self.premise_canvas.yview_scroll(int(-1*(event.delta/120)), "units")
def savePremises(self):
with open('Problem.txt', 'w') as f:
if len(self.problems) == 0 or len(self.problems[-1].getConnectors()) == 0:
return
problem = self.problems[-1]
connectors = problem.getConnectors()
for con in range(len(connectors)):
latex_str= connectors[con].getLatexString()
latex_str = "$$" + latex_str + "$$"
if (con == len(connectors) - 1):
latex_str = 'Conclusion: ' + latex_str
else:
latex_str = "Premise " + str(con + 1) + ": " + latex_str
f.write(latex_str)
f.write("\n")
return
def initiate_gui(self):
# Forcing different columns to be set width for the UI so it can only get so small
self.master.columnconfigure(1, weight =1, minsize=150)
self.master.columnconfigure(2, weight =1, minsize=150)
self.master.columnconfigure(3, weight =1, minsize=150)
self.master.columnconfigure(4, weight =1, minsize=150)
self.master.columnconfigure(5, weight =1, minsize=50)
self.master.columnconfigure(6, weight =1, minsize=220)
self.premise_frame = Frame(self.master, width=1200, height=300)
self.premise_frame.grid(column=1, row=3, columnspan= 7)
self.premise_frame.grid_rowconfigure(0, weight=1)
self.premise_frame.grid_columnconfigure(0, weight=1)
#self.premise_frame.grid_propagate(False)
self.premise_canvas = Canvas(self.premise_frame, bg = "white", width=1200, height=300)
self.premise_canvas.grid(row =0, column=0, sticky="news", columnspan=7)
self.vsb = Scrollbar(self.premise_frame, orient='vertical', command=self.premise_canvas.yview)
self.premise_canvas.config(yscrollcommand=self.vsb.set)
self.premise_canvas.bind_all("<MouseWheel>", self._on_mousewheel)
self.vsb.grid(row = 0, column= 1, rowspan=4, sticky= 'ns')
self.connector_frame = Frame(self.premise_canvas, bg = 'blue')
self.premise_canvas.create_window((0,0), window=self.connector_frame, anchor='center')
# Make a text box to input values instead
self.variable_input = Spinbox(self.master, from_ = 1, to = 100, textvariable=self.num_variables, font=('helvetica', 20))
self.variable_input_label = Label(self.master, text = "# of Variables", font=('helvetica', 15))
self.num_variables.trace('w', self.updateComplexity)
# Make a text box to input values instead
self.premise_input = Spinbox(self.master, from_ = 0, to = 1, font=('helvetica', 20))
self.premise_input_label = Label(self.master, text = "# of Premises", font=('helvetica', 15))
# Make a textbox to change sizey
self.complexity_input = Spinbox(self.master, from_ = 1, to = 100, textvariable=self.num_complexity, font=('helvetica', 20))
self.complexity_label = Label(self.master, text = "'Complexity'", font=('helvetica', 15))
# Button to clear the potential
self.generate_problem = Button(self.master, command = self.generateProblem, text = "Generate", font=('helvetica', 16))
# Button to clear the potential
self.can_satisfy = Button(self.master, command = self.swapValidity, text = " ", bg = 'green', font=('helvetica', 16))
# Button to clear the potential
self.generate_premises = Button(self.master, command = self.generatePremises, text = "Generate Premises", font=('helvetica', 16))
# Button to save the premises
self.save_premises = Button(self.master, command = self.savePremises, text = "Save Premises", font = ('helvetica', 16))
# Canvas to draw the tree onto
self.canvas = Canvas(self.master, bg="SpringGreen2", width= 1200, height = 600)
def draw(self):
# Draw variable_input
self.variable_input.grid(column = 2, row = 1, columnspan= 1, padx = 10, pady=10)
self.variable_input_label.grid(column = 2, row = 0, columnspan= 1)
# Draw premise_input
self.premise_input.grid(column = 3, row = 1, columnspan= 1, padx = 10, pady=10)
self.premise_input_label.grid(column = 3, row = 0, columnspan= 1)
# Draw the sizey input and label
self.complexity_input.grid(column = 4, row = 1, columnspan= 1, padx = 10, pady=10)
self.complexity_label.grid(column = 4, row = 0, columnspan= 1)
# Draw the button to generate the problem and swap if it is valid
self.generate_problem.grid(column = 1, row = 1, columnspan= 1, padx = 10, pady=10)
# Draw the button to generate the problem and swap if it is valid
self.generate_premises.grid(column = 6, row = 1, columnspan= 1, padx = 10, pady=10)
# Draw the save premis buttton
self.save_premises.grid(column= 7, row= 1, columnspan= 1, padx=10, pady=10)
self.can_satisfy.grid(column=5, row=1, columnspan=1, pady=10)
# Draw the canvas and scroll bar
self.canvas.grid(column = 1, row = 2, columnspan= 7)
return
def forget(self):
# Forget variable_input
self.variable_input.grid_forget()
self.variable_input_label.grid_forget()
# Forget premise_input
self.premise_input.grid_forget()
self.premise_input_label.grid_forget()
# Forget the complexity input and label
self.complexity_input.grid_forget()
self.complexity_label.grid_forget()
# Forget the satisfiablility button
self.can_satisfy.grid_forget()
# Forget the button to generate
self.generate_problem.grid_forget()
# Forget the button to generate
self.generate_premises.grid_forget()
#Forge the save premises button
self.save_premises.grid_forget()
# if __name__ == "__main__": lmao
if __name__ == "__main__" :
app = Tk()
everything = Main_Application(app)
app.mainloop()