TroglodyteDerivations commited on
Commit
52627b2
·
verified ·
1 Parent(s): c87d51c

Upload 5 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ Concepts[[:space:]]Deriving[[:space:]]From[[:space:]]Problem[[:space:]]for[[:space:]]PyQt5[[:space:]]Circuit[[:space:]]Solver/Screenshot[[:space:]]2025-11-04[[:space:]]at[[:space:]]1.51.48 PM.png filter=lfs diff=lfs merge=lfs -text
37
+ Concepts[[:space:]]Deriving[[:space:]]From[[:space:]]Problem[[:space:]]for[[:space:]]PyQt5[[:space:]]Circuit[[:space:]]Solver/Screenshot[[:space:]]2025-11-04[[:space:]]at[[:space:]]1.52.03 PM.png filter=lfs diff=lfs merge=lfs -text
38
+ output.mp4 filter=lfs diff=lfs merge=lfs -text
Concepts Deriving From Problem for PyQt5 Circuit Solver/Screenshot 2025-11-04 at 1.51.48 PM.png ADDED

Git LFS Details

  • SHA256: ef30c5f27d2d1bb6ba0b47a90166742c08158df3d149ede0529a916b9bd6e57a
  • Pointer size: 131 Bytes
  • Size of remote file: 140 kB
Concepts Deriving From Problem for PyQt5 Circuit Solver/Screenshot 2025-11-04 at 1.52.03 PM.png ADDED

Git LFS Details

  • SHA256: ede9cdc3ebaaeb8a03d705114e9d861a9e812ff3dc8434eae03fba3563bb7269
  • Pointer size: 131 Bytes
  • Size of remote file: 351 kB
app.py ADDED
@@ -0,0 +1,372 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ import numpy as np
3
+ import random
4
+ from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
5
+ QHBoxLayout, QPushButton, QTextEdit, QLabel,
6
+ QTabWidget, QTableWidget, QTableWidgetItem,
7
+ QHeaderView, QGroupBox, QSpinBox, QDoubleSpinBox,
8
+ QFormLayout)
9
+ from PyQt5.QtCore import Qt, QThread, pyqtSignal
10
+ import matplotlib.pyplot as plt
11
+ from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
12
+ from matplotlib.figure import Figure
13
+
14
+ class Particle:
15
+ def __init__(self, dim, bounds):
16
+ self.position = np.array([random.uniform(bounds[i][0], bounds[i][1]) for i in range(dim)])
17
+ self.velocity = np.array([random.uniform(-1, 1) for _ in range(dim)])
18
+ self.best_position = self.position.copy()
19
+ self.best_value = float('inf')
20
+ self.value = float('inf')
21
+
22
+ def update_velocity(self, global_best_position, w=0.5, c1=1.5, c2=1.5):
23
+ r1, r2 = random.random(), random.random()
24
+ cognitive = c1 * r1 * (self.best_position - self.position)
25
+ social = c2 * r2 * (global_best_position - self.position)
26
+ self.velocity = w * self.velocity + cognitive + social
27
+
28
+ def update_position(self, bounds):
29
+ self.position += self.velocity
30
+ # Apply bounds
31
+ for i in range(len(self.position)):
32
+ if self.position[i] < bounds[i][0]:
33
+ self.position[i] = bounds[i][0]
34
+ elif self.position[i] > bounds[i][1]:
35
+ self.position[i] = bounds[i][1]
36
+
37
+ def evaluate(self, cost_function):
38
+ self.value = cost_function(self.position)
39
+ if self.value < self.best_value:
40
+ self.best_value = self.value
41
+ self.best_position = self.position.copy()
42
+
43
+ class PSOThread(QThread):
44
+ update_signal = pyqtSignal(str, int, float, list)
45
+ finished_signal = pyqtSignal(list, list)
46
+
47
+ def __init__(self, cost_function, bounds, num_particles=30, max_iter=100):
48
+ super().__init__()
49
+ self.cost_function = cost_function
50
+ self.bounds = bounds
51
+ self.num_particles = num_particles
52
+ self.max_iter = max_iter
53
+ self.dim = len(bounds)
54
+ self.running = True
55
+
56
+ def run(self):
57
+ # Initialize particles
58
+ particles = [Particle(self.dim, self.bounds) for _ in range(self.num_particles)]
59
+ global_best_position = particles[0].position.copy()
60
+ global_best_value = float('inf')
61
+
62
+ # Find initial global best
63
+ for particle in particles:
64
+ particle.evaluate(self.cost_function)
65
+ if particle.best_value < global_best_value:
66
+ global_best_value = particle.best_value
67
+ global_best_position = particle.best_position.copy()
68
+
69
+ # PSO main loop
70
+ iteration_data = []
71
+ position_data = []
72
+
73
+ for iteration in range(self.max_iter):
74
+ if not self.running:
75
+ break
76
+
77
+ for particle in particles:
78
+ particle.update_velocity(global_best_position)
79
+ particle.update_position(self.bounds)
80
+ particle.evaluate(self.cost_function)
81
+
82
+ if particle.best_value < global_best_value:
83
+ global_best_value = particle.best_value
84
+ global_best_position = particle.best_position.copy()
85
+
86
+ # Store data for plotting
87
+ iteration_data.append(iteration + 1)
88
+ position_data.append(global_best_position.copy())
89
+
90
+ # Emit update signal
91
+ self.update_signal.emit(
92
+ f"Iteration {iteration+1}/{self.max_iter}",
93
+ iteration+1,
94
+ global_best_value,
95
+ global_best_position.tolist()
96
+ )
97
+
98
+ self.finished_signal.emit(iteration_data, position_data)
99
+
100
+ def stop(self):
101
+ self.running = False
102
+
103
+ class CircuitExample:
104
+ def __init__(self, example_num):
105
+ self.example_num = example_num
106
+ self.R1 = example_num # Ohms
107
+ self.V_out = example_num # Ohms
108
+ self.C1 = self.C2 = 1/(example_num + 1) # 1/s Ohms
109
+ self.L1 = self.L2 = 0.5 + 0.1 * example_num # s Ohms
110
+ self.V1 = self.V2 = example_num # Volts
111
+ self.alpha = self.R1
112
+
113
+ def get_description(self):
114
+ return f"""
115
+ Example {self.example_num}:
116
+ - R1 = {self.R1} Ω
117
+ - V_out(s) = {self.V_out} Ω
118
+ - C1 = C2 = {self.C1:.3f}/s Ω
119
+ - L1 = L2 = {self.L2:.3f}s Ω
120
+ - V1 = V2 = {self.V1} V
121
+ - α = {self.alpha}
122
+ """
123
+
124
+ def theoretical_impedance(self, s):
125
+ # Theoretical impedance: Z(s) = αs
126
+ return self.alpha * s
127
+
128
+ def cost_function(self, x):
129
+ # x[0] is the estimated alpha
130
+ # We'll evaluate at multiple s values to get a better estimate
131
+ s_values = [0.1, 0.5, 1.0, 2.0, 5.0]
132
+ error = 0
133
+ for s in s_values:
134
+ theoretical = self.theoretical_impedance(s)
135
+ estimated = x[0] * s
136
+ error += (theoretical - estimated) ** 2
137
+ return error
138
+
139
+ class MplCanvas(FigureCanvas):
140
+ def __init__(self, parent=None, width=5, height=4, dpi=100):
141
+ self.fig = Figure(figsize=(width, height), dpi=dpi)
142
+ super().__init__(self.fig)
143
+ self.setParent(parent)
144
+
145
+ def plot_convergence(self, iterations, best_values):
146
+ self.fig.clear()
147
+ ax = self.fig.add_subplot(111)
148
+ ax.plot(iterations, best_values, 'b-', linewidth=2)
149
+ ax.set_xlabel('Iteration')
150
+ ax.set_ylabel('Best Cost Value')
151
+ ax.set_title('PSO Convergence')
152
+ ax.grid(True)
153
+ self.draw()
154
+
155
+ def plot_parameter_evolution(self, iterations, parameters):
156
+ self.fig.clear()
157
+ ax = self.fig.add_subplot(111)
158
+ for i in range(len(parameters[0])):
159
+ param_values = [p[i] for p in parameters]
160
+ ax.plot(iterations, param_values, label=f'Parameter {i+1}')
161
+ ax.set_xlabel('Iteration')
162
+ ax.set_ylabel('Parameter Value')
163
+ ax.set_title('Parameter Evolution')
164
+ ax.legend()
165
+ ax.grid(True)
166
+ self.draw()
167
+
168
+ class PSOCircuitApp(QMainWindow):
169
+ def __init__(self):
170
+ super().__init__()
171
+ self.examples = [CircuitExample(i+1) for i in range(10)]
172
+ self.current_example = 0
173
+ self.pso_thread = None
174
+ self.init_ui()
175
+
176
+ def init_ui(self):
177
+ self.setWindowTitle("PSO Circuit Analysis")
178
+ self.setGeometry(100, 100, 1200, 800)
179
+
180
+ # Central widget and main layout
181
+ central_widget = QWidget()
182
+ self.setCentralWidget(central_widget)
183
+ main_layout = QHBoxLayout(central_widget)
184
+
185
+ # Left panel for controls and info
186
+ left_panel = QVBoxLayout()
187
+
188
+ # Example selection
189
+ example_group = QGroupBox("Circuit Examples")
190
+ example_layout = QVBoxLayout()
191
+
192
+ self.example_combo = QSpinBox()
193
+ self.example_combo.setMinimum(1)
194
+ self.example_combo.setMaximum(10)
195
+ self.example_combo.valueChanged.connect(self.change_example)
196
+
197
+ self.example_info = QTextEdit()
198
+ self.example_info.setMaximumHeight(200)
199
+ self.example_info.setReadOnly(True)
200
+
201
+ example_layout.addWidget(QLabel("Select Example:"))
202
+ example_layout.addWidget(self.example_combo)
203
+ example_layout.addWidget(QLabel("Circuit Parameters:"))
204
+ example_layout.addWidget(self.example_info)
205
+ example_group.setLayout(example_layout)
206
+ left_panel.addWidget(example_group)
207
+
208
+ # PSO controls
209
+ pso_group = QGroupBox("PSO Parameters")
210
+ pso_layout = QFormLayout()
211
+
212
+ self.num_particles_spin = QSpinBox()
213
+ self.num_particles_spin.setMinimum(10)
214
+ self.num_particles_spin.setMaximum(100)
215
+ self.num_particles_spin.setValue(30)
216
+
217
+ self.max_iter_spin = QSpinBox()
218
+ self.max_iter_spin.setMinimum(10)
219
+ self.max_iter_spin.setMaximum(500)
220
+ self.max_iter_spin.setValue(100)
221
+
222
+ self.w_spin = QDoubleSpinBox()
223
+ self.w_spin.setMinimum(0.1)
224
+ self.w_spin.setMaximum(2.0)
225
+ self.w_spin.setValue(0.5)
226
+ self.w_spin.setSingleStep(0.1)
227
+
228
+ self.c1_spin = QDoubleSpinBox()
229
+ self.c1_spin.setMinimum(0.1)
230
+ self.c1_spin.setMaximum(3.0)
231
+ self.c1_spin.setValue(1.5)
232
+ self.c1_spin.setSingleStep(0.1)
233
+
234
+ self.c2_spin = QDoubleSpinBox()
235
+ self.c2_spin.setMinimum(0.1)
236
+ self.c2_spin.setMaximum(3.0)
237
+ self.c2_spin.setValue(1.5)
238
+ self.c2_spin.setSingleStep(0.1)
239
+
240
+ pso_layout.addRow("Number of Particles:", self.num_particles_spin)
241
+ pso_layout.addRow("Maximum Iterations:", self.max_iter_spin)
242
+ pso_layout.addRow("Inertia Weight (w):", self.w_spin)
243
+ pso_layout.addRow("Cognitive Parameter (c1):", self.c1_spin)
244
+ pso_layout.addRow("Social Parameter (c2):", self.c2_spin)
245
+
246
+ pso_group.setLayout(pso_layout)
247
+ left_panel.addWidget(pso_group)
248
+
249
+ # Control buttons
250
+ self.run_button = QPushButton("Run PSO")
251
+ self.run_button.clicked.connect(self.run_pso)
252
+
253
+ self.stop_button = QPushButton("Stop PSO")
254
+ self.stop_button.clicked.connect(self.stop_pso)
255
+ self.stop_button.setEnabled(False)
256
+
257
+ left_panel.addWidget(self.run_button)
258
+ left_panel.addWidget(self.stop_button)
259
+
260
+ # Results display
261
+ results_group = QGroupBox("Results")
262
+ results_layout = QVBoxLayout()
263
+
264
+ self.results_text = QTextEdit()
265
+ self.results_text.setMaximumHeight(150)
266
+ self.results_text.setReadOnly(True)
267
+
268
+ results_layout.addWidget(self.results_text)
269
+ results_group.setLayout(results_layout)
270
+ left_panel.addWidget(results_group)
271
+
272
+ # Add left panel to main layout
273
+ main_layout.addLayout(left_panel, 1)
274
+
275
+ # Right panel for plots
276
+ right_panel = QVBoxLayout()
277
+
278
+ # Tab widget for different plots
279
+ self.plot_tabs = QTabWidget()
280
+
281
+ # Convergence plot
282
+ self.convergence_canvas = MplCanvas(self, width=5, height=4, dpi=100)
283
+ self.plot_tabs.addTab(self.convergence_canvas, "Convergence")
284
+
285
+ # Parameter evolution plot
286
+ self.param_canvas = MplCanvas(self, width=5, height=4, dpi=100)
287
+ self.plot_tabs.addTab(self.param_canvas, "Parameter Evolution")
288
+
289
+ right_panel.addWidget(self.plot_tabs)
290
+
291
+ # Add right panel to main layout
292
+ main_layout.addLayout(right_panel, 2)
293
+
294
+ # Initialize with first example
295
+ self.change_example(1)
296
+
297
+ def change_example(self, value):
298
+ self.current_example = value - 1
299
+ example = self.examples[self.current_example]
300
+ self.example_info.setText(example.get_description())
301
+ self.results_text.clear()
302
+
303
+ def run_pso(self):
304
+ example = self.examples[self.current_example]
305
+
306
+ # Define bounds for alpha (0 to 2*expected alpha)
307
+ bounds = [(0.1, 2 * example.alpha)]
308
+
309
+ # Create and configure PSO thread
310
+ self.pso_thread = PSOThread(
311
+ example.cost_function,
312
+ bounds,
313
+ self.num_particles_spin.value(),
314
+ self.max_iter_spin.value()
315
+ )
316
+
317
+ # Connect signals
318
+ self.pso_thread.update_signal.connect(self.update_progress)
319
+ self.pso_thread.finished_signal.connect(self.pso_finished)
320
+
321
+ # Update UI
322
+ self.run_button.setEnabled(False)
323
+ self.stop_button.setEnabled(True)
324
+ self.results_text.clear()
325
+ self.results_text.append("Running PSO...")
326
+
327
+ # Start PSO
328
+ self.pso_thread.start()
329
+
330
+ def stop_pso(self):
331
+ if self.pso_thread and self.pso_thread.isRunning():
332
+ self.pso_thread.stop()
333
+ self.pso_thread.wait()
334
+ self.results_text.append("PSO stopped by user.")
335
+ self.run_button.setEnabled(True)
336
+ self.stop_button.setEnabled(False)
337
+
338
+ def update_progress(self, status, iteration, best_value, best_position):
339
+ example = self.examples[self.current_example]
340
+ self.results_text.clear()
341
+ self.results_text.append(f"Status: {status}")
342
+ self.results_text.append(f"Best Cost: {best_value:.6f}")
343
+ self.results_text.append(f"Estimated α: {best_position[0]:.4f}")
344
+ self.results_text.append(f"Theoretical α: {example.alpha}")
345
+ self.results_text.append(f"Error: {abs(best_position[0] - example.alpha):.4f}")
346
+
347
+ def pso_finished(self, iterations, positions):
348
+ example = self.examples[self.current_example]
349
+ best_alpha = positions[-1][0]
350
+
351
+ self.results_text.append("\n--- PSO Completed ---")
352
+ self.results_text.append(f"Final Estimated α: {best_alpha:.4f}")
353
+ self.results_text.append(f"Theoretical α: {example.alpha}")
354
+ self.results_text.append(f"Absolute Error: {abs(best_alpha - example.alpha):.4f}")
355
+ self.results_text.append(f"Relative Error: {abs(best_alpha - example.alpha)/example.alpha*100:.2f}%")
356
+
357
+ # Plot convergence
358
+ best_values = [example.cost_function(p) for p in positions]
359
+ self.convergence_canvas.plot_convergence(iterations, best_values)
360
+
361
+ # Plot parameter evolution
362
+ self.param_canvas.plot_parameter_evolution(iterations, positions)
363
+
364
+ # Update UI
365
+ self.run_button.setEnabled(True)
366
+ self.stop_button.setEnabled(False)
367
+
368
+ if __name__ == "__main__":
369
+ app = QApplication(sys.argv)
370
+ window = PSOCircuitApp()
371
+ window.show()
372
+ sys.exit(app.exec_())
output.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4a1c878815d622346b814e3bbce0437f673e6961b14e1307739d46d36e8aa9e6
3
+ size 12506911
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ PyQt5
2
+ matplotlib
3
+ numpy