-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.py
263 lines (223 loc) · 10.9 KB
/
app.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
import imgui
from imgui.integrations.glfw import GlfwRenderer
import glfw
try:
# for the exe all files are in root
from addingactscons import AddingActsCons
from deasolver import DEASolver
from dualsimplex import DualSimplex
from lpduality import LPDuality
from penaltiessimplex import PenaltiesSimplex
from preemptivesimplex import PreemptiveSimplex
from graphicalsolver import GraphicalSolver
from mathpreliminaries import MathPreliminaries
from sensitivityAnalysis import SensitivityAnalysis
from twophasesimplex import TwoPhaseSimplex
except:
try:
from LPSolverTools.addingActsCons.addingactscons import AddingActsCons
from LPSolverTools.DEA.deasolver import DEASolver
from LPSolverTools.dual.dualsimplex import DualSimplex
from LPSolverTools.duality.lpduality import LPDuality
from LPSolverTools.goal.penaltiessimplex.penaltiessimplex import PenaltiesSimplex
from LPSolverTools.goal.preemptivesimplex.preemptivesimplex import PreemptiveSimplex
from LPSolverTools.graphicalSolver.graphicalsolver import GraphicalSolver
from LPSolverTools.mathPrelim.mathpreliminaries import MathPreliminaries
from LPSolverTools.sensitivityAnalysis.sensitivityanalysis import SensitivityAnalysis
from LPSolverTools.twoPhase.twophasesimplex import TwoPhaseSimplex
except:
print("Could not import modules")
class App:
def __init__(self):
# initialize tools
self.addingActsCons = AddingActsCons()
self.deaSolver = DEASolver()
self.dualSimplex = DualSimplex()
self.lPDuality = LPDuality()
self.penaltiesSimplex = PenaltiesSimplex()
self.preemptiveSimplex = PreemptiveSimplex()
self.graphicalSolver = GraphicalSolver()
self.mathPreliminaries = MathPreliminaries()
self.sensitivityAnalysis = SensitivityAnalysis()
self.twoPhaseSimplex = TwoPhaseSimplex()
self.currentTool = 0
self.paddingTop = 18
self.buttonLabels = [
"Menu", "Adding Acts, Cons", "DEA Solver",
"Dual Simplex", "Duality", "Goal Penalties",
"Goal Preemptive", "Graphical Solver",
"Preliminaries", "Sensitivity Analysis", "Two Phase Simplex", "Help"
]
self.originalButtonColor = ()
self.hoveredButtonColor = ()
self.selectedButtonColor = ()
self.activeButtonColor = ()
self.toolUIs = {
0: self.imguiMainMenu,
1: self.addingActsCons.imguiUIElements,
2: self.deaSolver.imguiUIElements,
3: self.dualSimplex.imguiUIElements,
4: self.lPDuality.imguiUIElements,
5: self.penaltiesSimplex.imguiUIElements,
6: self.preemptiveSimplex.imguiUIElements,
7: self.graphicalSolver.imguiUIElements,
8: self.mathPreliminaries.imguiUIElements,
9: self.sensitivityAnalysis.imguiUIElements,
10: self.twoPhaseSimplex.imguiUIElements,
11: self.imguiHelpMenu
}
def imguiMainMenu(self, windowSize, windowPosX=0, windowPosY=0):
imgui.set_next_window_position(
windowPosX, windowPosY) # Set the window position
imgui.set_next_window_size(
(windowSize[0]), (windowSize[1])) # Set the window size
imgui.begin("Main Menu",
flags=imgui.WINDOW_NO_TITLE_BAR | imgui.WINDOW_NO_RESIZE)
midX = (windowSize[0] / 2) - 100
midY = windowSize[1] / 2
imgui.spacing()
imgui.spacing()
imgui.spacing()
imgui.spacing()
imgui.set_cursor_pos_x(midX - 100)
imgui.text(
"Welcome To Linier Programming Tool Prototypes!\nBy Brett Wilson")
imgui.spacing()
imgui.spacing()
for i in range(1, len(self.buttonLabels)):
imgui.spacing()
imgui.spacing()
imgui.set_cursor_pos_x(midX)
if imgui.button(self.buttonLabels[i], width=200):
self.currentTool = i
imgui.spacing()
imgui.spacing()
imgui.set_cursor_pos_x(midX - 20)
imgui.text("See Help for more info!")
imgui.end()
def imguiHelpMenu(self, windowSize, windowPosX=0, windowPosY=0):
imgui.set_next_window_position(
windowPosX, windowPosY) # Set the window position
imgui.set_next_window_size(
(windowSize[0]), (windowSize[1])) # Set the window size
imgui.begin("Help Menu",
# flags=imgui.WINDOW_NO_TITLE_BAR | imgui.WINDOW_NO_RESIZE | imgui.WINDOW_ALWAYS_HORIZONTAL_SCROLLBAR)
flags=imgui.WINDOW_NO_TITLE_BAR | imgui.WINDOW_NO_RESIZE | imgui.WINDOW_ALWAYS_HORIZONTAL_SCROLLBAR )
imgui.begin_child("Scrollable Child", width=0, height=0,
border=True, flags=imgui.WINDOW_ALWAYS_HORIZONTAL_SCROLLBAR)
imgui.text("LP Tool by Brett Wilson: Github.com/brettwilsonbdw")
helpTextInput = (
"In the Input:\n\n"
"Click on the boxes and enter values.\n\n"
"Objective Variables: x1, x2, x3, etc. are your objective variables (also known as decision variables). Both decision variables and constraints can be increased or decreased using their respective '+' and '-' buttons.\n\n"
"Constraints also use x1, x2, x3, etc. Align their respective values with the objective variables. Use the drop-down box to select the constraint type (<=, >=).\n\n"
"Use the radio buttons to choose between 'Maximize' or 'Minimize'.\n\n"
"Click 'Solve' to run the solver.\n\n"
"Click 'Reset' to clear all inputs.\n\n"
"If no output appears, check if your input is correct. Most likely, an error in the input is causing the issue."
)
imgui.spacing()
imgui.spacing()
imgui.spacing()
imgui.spacing()
imgui.separator()
imgui.text(helpTextInput)
helpTextOutput = (
"In the output:\n\n"
"The header will have:\n"
"- 'x' for objective values\n"
"- 's' for slack\n"
"- 'e' for excess\n"
"- 'rhs' for right-hand side values\n\n"
"For the columns:\n"
"- 'c' represents constraints with the constraint number\n"
"- 'z' represents the objective row\n\n"
"The optimal tableau will have the words optimal tableau or be the last tableau.\n\n"
"The optimal value is in the top right corner of each tableau under rhs.\n\n"
"The pivot row and column will be highlighted.\n\n"
)
imgui.spacing()
imgui.spacing()
imgui.spacing()
imgui.spacing()
imgui.separator()
imgui.text(helpTextOutput)
helpTextExtra = (
"Extras:\n\n"
"For Goal Simplex:\n"
"The header will include 'g-' and 'g+' indicating the goal with its number.\n"
"There is also a 'Show Goal Order' button that allows you to rearrange the goals from top to bottom, indicating their importance from most to least important.\n\n"
"In Duality:\n"
"There will be an extra 'slack' column and a 'ref' column. The 'ref' column can be safely ignored, based on the Excel Solver way of showing results.\n\n"
"In DEA (Data Envelopment Analysis):\n"
"The 'ref' column can be safely ignored, similar to Duality.\n\n"
"In Adding Acts and Cons:\n"
"'Acts' stands for activities (e.g., x1, x2) and 'cons' stands for constraints there is a radio button to select each. There is an 'Abs On/Off' radio button to force the underlying initial tableau to be all positive.\n\n"
"In Mathematical Preliminaries:\n"
"The 'Abs' radio button is also present, allowing the same functionality as in Adding Acts and Cons. Additionally, there is a 'Lock Tab' radio button to prevent the table from automatically being the most optimal, enabling some sensitivity analysis from the first table input.\n\n"
"In both Adding Acts/Cons and Mathematical Preliminaries:\n"
"There is an 'Optimize' button which will re-solve the current adjusted table to be optimal.\n\n"
"In Mathematical Preliminaries:\n"
"You can enter values with the words '+d' for delta. This will perform algebraic calculations and display the results in each respective part. There is also a 'Solve Delta' radio button to compute the delta for the RHS equation in the changing table.\n\n"
"For Constraints:\n"
"Most tools do not have an '=' option in the drop-down. Instead, you must create two constraints for an '=' constraint: one as '>=' and the other as '<='. There is no need to adjust positive and negative signs."
)
imgui.spacing()
imgui.spacing()
imgui.spacing()
imgui.spacing()
imgui.separator()
imgui.text(helpTextExtra)
imgui.end_child()
imgui.end()
def DoGui(self):
# Initialize GLFW
if not glfw.init():
print("Could not initialize OpenGL context")
return
# Create a windowed mode window and its OpenGL context
window = glfw.create_window(
1280, 720, "Linier Programming Tool Prototypes", None, None)
if not window:
glfw.terminate()
return
# Make the window's context current
glfw.make_context_current(window)
# Initialize ImGui
imgui.create_context()
impl = GlfwRenderer(window)
while not glfw.window_should_close(window):
glfw.poll_events()
impl.process_inputs()
windowSize = glfw.get_window_size(window)
imgui.new_frame()
if imgui.begin_main_menu_bar():
if imgui.button(self.buttonLabels[0]):
self.currentTool = 0
if imgui.button("LP Tools"):
imgui.open_popup("LP Tools")
imgui.set_next_window_position(0, self.paddingTop)
if imgui.begin_popup("LP Tools"):
for i, label in enumerate(self.buttonLabels[1:-1], start=1):
clicked, _ = imgui.menu_item(label, "", self.currentTool == i)
if clicked:
self.currentTool = i
imgui.end_popup()
if imgui.button(self.buttonLabels[-1]):
self.currentTool = len(self.buttonLabels) - 1
imgui.end_main_menu_bar()
# set the tool UI to display
if self.currentTool in self.toolUIs:
self.toolUIs[self.currentTool](windowSize, 0, self.paddingTop)
# Rendering
imgui.render()
impl.render(imgui.get_draw_data())
glfw.swap_buffers(window)
# Cleanup
impl.shutdown()
glfw.terminate()
def main():
app = App()
app.DoGui()
if __name__ == "__main__":
main()