| | import sys |
| | import numpy as np |
| | import matplotlib.pyplot as plt |
| | from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas |
| | from matplotlib.figure import Figure |
| | from mpl_toolkits.mplot3d import Axes3D |
| | import random |
| | from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, |
| | QWidget, QComboBox, QPushButton, QLabel, QSpinBox, |
| | QDoubleSpinBox, QGroupBox, QGridLayout, QTextEdit, |
| | QSplitter, QProgressBar) |
| | from PyQt5.QtCore import QTimer, Qt |
| | from PyQt5.QtGui import QFont |
| |
|
| | class Particle: |
| | def __init__(self, dim, bounds): |
| | self.dim = dim |
| | self.position = np.array([random.uniform(bounds[i][0], bounds[i][1]) for i in range(dim)]) |
| | self.velocity = np.array([random.uniform(-1, 1) for _ in range(dim)]) |
| | self.best_position = self.position.copy() |
| | self.best_value = float('inf') |
| | self.bounds = bounds |
| | |
| | def update_velocity(self, global_best_position, w, c1, c2): |
| | for i in range(self.dim): |
| | r1, r2 = random.random(), random.random() |
| | cognitive = c1 * r1 * (self.best_position[i] - self.position[i]) |
| | social = c2 * r2 * (global_best_position[i] - self.position[i]) |
| | self.velocity[i] = w * self.velocity[i] + cognitive + social |
| | |
| | def update_position(self): |
| | self.position += self.velocity |
| | |
| | for i in range(self.dim): |
| | if self.position[i] < self.bounds[i][0]: |
| | self.position[i] = self.bounds[i][0] |
| | self.velocity[i] *= -0.5 |
| | elif self.position[i] > self.bounds[i][1]: |
| | self.position[i] = self.bounds[i][1] |
| | self.velocity[i] *= -0.5 |
| |
|
| | class PSO: |
| | def __init__(self, objective_func, dim, bounds, num_particles=30, w=0.7, c1=1.4, c2=1.4): |
| | self.objective_func = objective_func |
| | self.dim = dim |
| | self.bounds = bounds |
| | self.num_particles = num_particles |
| | self.w = w |
| | self.c1 = c1 |
| | self.c2 = c2 |
| | |
| | self.particles = [Particle(dim, bounds) for _ in range(num_particles)] |
| | self.global_best_position = np.array([random.uniform(bounds[i][0], bounds[i][1]) for i in range(dim)]) |
| | self.global_best_value = float('inf') |
| | self.history = [] |
| | |
| | def optimize(self, max_iterations): |
| | for iteration in range(max_iterations): |
| | for particle in self.particles: |
| | |
| | value = self.objective_func(particle.position) |
| | |
| | |
| | if value < particle.best_value: |
| | particle.best_value = value |
| | particle.best_position = particle.position.copy() |
| | |
| | |
| | if value < self.global_best_value: |
| | self.global_best_value = value |
| | self.global_best_position = particle.position.copy() |
| | |
| | |
| | for particle in self.particles: |
| | particle.update_velocity(self.global_best_position, self.w, self.c1, self.c2) |
| | particle.update_position() |
| | |
| | |
| | self.history.append({ |
| | 'positions': [p.position.copy() for p in self.particles], |
| | 'global_best': self.global_best_position.copy(), |
| | 'global_best_value': self.global_best_value, |
| | 'iteration': iteration |
| | }) |
| | |
| | return self.global_best_position, self.global_best_value |
| |
|
| | class EquationDefinitions: |
| | @staticmethod |
| | def get_equations(): |
| | equations = { |
| | |
| | "Sphere Function": { |
| | "func": lambda x: sum(xi**2 for xi in x), |
| | "dim": 2, |
| | "bounds": [(-5.12, 5.12), (-5.12, 5.12)], |
| | "description": "f(x,y) = x² + y²\nMinimum at (0,0)" |
| | }, |
| | "Rosenbrock Function": { |
| | "func": lambda x: 100*(x[1]-x[0]**2)**2 + (1-x[0])**2, |
| | "dim": 2, |
| | "bounds": [(-2, 2), (-1, 3)], |
| | "description": "f(x,y) = 100(y-x²)² + (1-x)²\nMinimum at (1,1)" |
| | }, |
| | "Rastrigin Function": { |
| | "func": lambda x: 20 + sum(xi**2 - 10*np.cos(2*np.pi*xi) for xi in x), |
| | "dim": 2, |
| | "bounds": [(-5.12, 5.12), (-5.12, 5.12)], |
| | "description": "f(x,y) = 20 + x²+y² -10(cos(2πx)+cos(2πy))\nMinimum at (0,0)" |
| | }, |
| | "Ackley Function": { |
| | "func": lambda x: -20*np.exp(-0.2*np.sqrt(0.5*sum(xi**2 for xi in x))) - |
| | np.exp(0.5*sum(np.cos(2*np.pi*xi) for xi in x)) + 20 + np.e, |
| | "dim": 2, |
| | "bounds": [(-5, 5), (-5, 5)], |
| | "description": "Complex function with many local minima\nMinimum at (0,0)" |
| | }, |
| | "Matyas Function": { |
| | "func": lambda x: 0.26*(x[0]**2 + x[1]**2) - 0.48*x[0]*x[1], |
| | "dim": 2, |
| | "bounds": [(-10, 10), (-10, 10)], |
| | "description": "f(x,y) = 0.26(x²+y²) - 0.48xy\nMinimum at (0,0)" |
| | }, |
| | "Himmelblau's Function": { |
| | "func": lambda x: (x[0]**2 + x[1] - 11)**2 + (x[0] + x[1]**2 - 7)**2, |
| | "dim": 2, |
| | "bounds": [(-5, 5), (-5, 5)], |
| | "description": "f(x,y) = (x²+y-11)² + (x+y²-7)²\n4 minima at (3,2), (-2.8,3.1), (-3.8,-3.3), (3.6,-1.8)" |
| | }, |
| | "Three-Hump Camel": { |
| | "func": lambda x: 2*x[0]**2 - 1.05*x[0]**4 + x[0]**6/6 + x[0]*x[1] + x[1]**2, |
| | "dim": 2, |
| | "bounds": [(-5, 5), (-5, 5)], |
| | "description": "f(x,y) = 2x² -1.05x⁴ + x⁶/6 + xy + y²\nMinimum at (0,0)" |
| | }, |
| | "Easom Function": { |
| | "func": lambda x: -np.cos(x[0])*np.cos(x[1])*np.exp(-((x[0]-np.pi)**2 + (x[1]-np.pi)**2)), |
| | "dim": 2, |
| | "bounds": [(-10, 10), (-10, 10)], |
| | "description": "f(x,y) = -cos(x)cos(y)exp(-((x-π)²+(y-π)²))\nMinimum at (π,π)" |
| | }, |
| | "Cross-in-Tray": { |
| | "func": lambda x: -0.0001*(abs(np.sin(x[0])*np.sin(x[1])*np.exp(abs(100-np.sqrt(x[0]**2+x[1]**2)/np.pi))) + 1)**0.1, |
| | "dim": 2, |
| | "bounds": [(-10, 10), (-10, 10)], |
| | "description": "Multiple global minima in cross pattern" |
| | }, |
| | "Holder Table": { |
| | "func": lambda x: -abs(np.sin(x[0])*np.cos(x[1])*np.exp(abs(1-np.sqrt(x[0]**2+x[1]**2)/np.pi))), |
| | "dim": 2, |
| | "bounds": [(-10, 10), (-10, 10)], |
| | "description": "Multiple minima in table-like pattern" |
| | }, |
| | |
| | |
| | "Sphere 3D": { |
| | "func": lambda x: sum(xi**2 for xi in x), |
| | "dim": 3, |
| | "bounds": [(-5.12, 5.12), (-5.12, 5.12), (-5.12, 5.12)], |
| | "description": "f(x,y,z) = x² + y² + z²\nMinimum at (0,0,0)" |
| | }, |
| | "Rosenbrock 3D": { |
| | "func": lambda x: sum(100*(x[i+1]-x[i]**2)**2 + (1-x[i])**2 for i in range(len(x)-1)), |
| | "dim": 3, |
| | "bounds": [(-2, 2), (-2, 2), (-2, 2)], |
| | "description": "3D extension of Rosenbrock\nMinimum at (1,1,1)" |
| | }, |
| | "Rastrigin 3D": { |
| | "func": lambda x: 30 + sum(xi**2 - 10*np.cos(2*np.pi*xi) for xi in x), |
| | "dim": 3, |
| | "bounds": [(-5.12, 5.12), (-5.12, 5.12), (-5.12, 5.12)], |
| | "description": "3D Rastrigin function\nMinimum at (0,0,0)" |
| | }, |
| | "Ackley 3D": { |
| | "func": lambda x: -20*np.exp(-0.2*np.sqrt(1/3*sum(xi**2 for xi in x))) - |
| | np.exp(1/3*sum(np.cos(2*np.pi*xi) for xi in x)) + 20 + np.e, |
| | "dim": 3, |
| | "bounds": [(-5, 5), (-5, 5), (-5, 5)], |
| | "description": "3D Ackley function\nMinimum at (0,0,0)" |
| | }, |
| | "Sum of Different Powers": { |
| | "func": lambda x: sum(abs(xi)**(i+2) for i, xi in enumerate(x)), |
| | "dim": 3, |
| | "bounds": [(-1, 1), (-1, 1), (-1, 1)], |
| | "description": "f(x,y,z) = |x|² + |y|³ + |z|⁴\nMinimum at (0,0,0)" |
| | }, |
| | "Rotated Hyper-Ellipsoid": { |
| | "func": lambda x: sum(sum(x[j]**2 for j in range(i+1)) for i in range(len(x))), |
| | "dim": 3, |
| | "bounds": [(-5.12, 5.12), (-5.12, 5.12), (-5.12, 5.12)], |
| | "description": "f(x,y,z) = x² + (x²+y²) + (x²+y²+z²)\nMinimum at (0,0,0)" |
| | }, |
| | "Zakharov 3D": { |
| | "func": lambda x: sum(xi**2 for xi in x) + (0.5*sum(i*xi for i, xi in enumerate(x, 1)))**2 + (0.5*sum(i*xi for i, xi in enumerate(x, 1)))**4, |
| | "dim": 3, |
| | "bounds": [(-5, 10), (-5, 10), (-5, 10)], |
| | "description": "Zakharov function in 3D\nMinimum at (0,0,0)" |
| | }, |
| | "Dixon-Price": { |
| | "func": lambda x: (x[0]-1)**2 + sum(i*(2*x[i]**2 - x[i-1])**2 for i in range(1, len(x))), |
| | "dim": 3, |
| | "bounds": [(-10, 10), (-10, 10), (-10, 10)], |
| | "description": "Dixon-Price function\nMinimum depends on dimension" |
| | }, |
| | "Levy 3D": { |
| | "func": lambda x: ( |
| | np.sin(np.pi * (1 + (x[0] - 1) / 4))**2 + |
| | sum( |
| | ((1 + (x[i] - 1) / 4 - 1)**2 * |
| | (1 + 10 * np.sin(np.pi * (1 + (x[i] - 1) / 4) + 1)**2)) |
| | for i in range(len(x) - 1) |
| | ) + |
| | ((1 + (x[-1] - 1) / 4 - 1)**2 * |
| | (1 + np.sin(2 * np.pi * (1 + (x[-1] - 1) / 4))**2)) |
| | ), |
| | "dim": 3, |
| | "bounds": [(-10, 10), (-10, 10), (-10, 10)], |
| | "description": "Levy function in 3D\nMinimum at (1,1,1)" |
| | }, |
| | "Michalewicz 3D": { |
| | "func": lambda x: -sum(np.sin(x[i]) * np.sin((i+1)*x[i]**2/np.pi)**20 for i in range(len(x))), |
| | "dim": 3, |
| | "bounds": [(0, np.pi), (0, np.pi), (0, np.pi)], |
| | "description": "Michalewicz function\nMany local minima, hard global optimization" |
| | } |
| | } |
| | return equations |
| |
|
| | class PlotCanvas(FigureCanvas): |
| | def __init__(self, parent=None, width=5, height=4, dpi=100, is_3d=False): |
| | self.fig = Figure(figsize=(width, height), dpi=dpi) |
| | super().__init__(self.fig) |
| | self.setParent(parent) |
| | self.is_3d = is_3d |
| | |
| | if is_3d: |
| | self.ax = self.fig.add_subplot(111, projection='3d') |
| | else: |
| | self.ax = self.fig.add_subplot(111) |
| | |
| | self.ax.grid(True, alpha=0.3) |
| | |
| | def plot_optimization(self, equation_info, particles_history, current_iteration): |
| | self.ax.clear() |
| | |
| | if current_iteration >= len(particles_history): |
| | return |
| | |
| | current_data = particles_history[current_iteration] |
| | positions = current_data['positions'] |
| | |
| | if equation_info['dim'] == 2: |
| | self._plot_2d(equation_info, positions, current_data) |
| | else: |
| | if self.is_3d: |
| | self._plot_3d(equation_info, positions, current_data) |
| | else: |
| | self._plot_3d_projection(equation_info, positions, current_data) |
| | |
| | self.ax.set_title(f'Iteration {current_iteration + 1}\nBest Value: {current_data["global_best_value"]:.6f}') |
| | self.draw() |
| | |
| | def _plot_2d(self, equation_info, positions, current_data): |
| | |
| | bounds = equation_info['bounds'] |
| | x = np.linspace(bounds[0][0], bounds[0][1], 100) |
| | y = np.linspace(bounds[1][0], bounds[1][1], 100) |
| | X, Y = np.meshgrid(x, y) |
| | Z = np.array([[equation_info['func']([xi, yi]) for xi in x] for yi in y]) |
| | |
| | |
| | contour = self.ax.contour(X, Y, Z, levels=20, alpha=0.6) |
| | self.ax.clabel(contour, inline=True, fontsize=8) |
| | |
| | |
| | particle_x = [p[0] for p in positions] |
| | particle_y = [p[1] for p in positions] |
| | self.ax.scatter(particle_x, particle_y, c='red', s=30, alpha=0.7, label='Particles') |
| | |
| | |
| | self.ax.scatter(current_data['global_best'][0], current_data['global_best'][1], |
| | c='green', s=100, marker='*', label='Global Best') |
| | |
| | self.ax.set_xlabel('X') |
| | self.ax.set_ylabel('Y') |
| | self.ax.legend() |
| | |
| | def _plot_3d(self, equation_info, positions, current_data): |
| | bounds = equation_info['bounds'] |
| | x = np.linspace(bounds[0][0], bounds[0][1], 30) |
| | y = np.linspace(bounds[1][0], bounds[1][1], 30) |
| | X, Y = np.meshgrid(x, y) |
| | |
| | |
| | if len(positions[0]) == 3: |
| | fixed_z = current_data['global_best'][2] |
| | Z = np.array([[equation_info['func']([xi, yi, fixed_z]) for xi in x] for yi in y]) |
| | |
| | |
| | self.ax.plot_surface(X, Y, Z, cmap='viridis', alpha=0.6) |
| | |
| | |
| | particle_x = [p[0] for p in positions] |
| | particle_y = [p[1] for p in positions] |
| | particle_z = [equation_info['func']([p[0], p[1], fixed_z]) for p in positions] |
| | self.ax.scatter(particle_x, particle_y, particle_z, c='red', s=30, alpha=0.7, label='Particles') |
| | |
| | |
| | best_x, best_y = current_data['global_best'][0], current_data['global_best'][1] |
| | best_z = equation_info['func']([best_x, best_y, fixed_z]) |
| | self.ax.scatter([best_x], [best_y], [best_z], c='green', s=100, marker='*', label='Global Best') |
| | |
| | self.ax.set_xlabel('X') |
| | self.ax.set_ylabel('Y') |
| | self.ax.set_zlabel('f(X,Y)') |
| | |
| | self.ax.legend() |
| |
|
| | def _plot_3d_projection(self, equation_info, positions, current_data): |
| | """2D projection of 3D function by fixing one dimension""" |
| | bounds = equation_info['bounds'] |
| | |
| | |
| | best_pos = current_data['global_best'] |
| | |
| | |
| | x = np.linspace(bounds[0][0], bounds[0][1], 100) |
| | y = np.linspace(bounds[1][0], bounds[1][1], 100) |
| | X, Y = np.meshgrid(x, y) |
| | |
| | |
| | fixed_z = best_pos[2] if len(best_pos) > 2 else 0 |
| | Z = np.array([[equation_info['func']([xi, yi, fixed_z]) for xi in x] for yi in y]) |
| | |
| | |
| | contour = self.ax.contour(X, Y, Z, levels=20, alpha=0.6) |
| | self.ax.clabel(contour, inline=True, fontsize=8) |
| | |
| | |
| | particle_x = [p[0] for p in positions] |
| | particle_y = [p[1] for p in positions] |
| | self.ax.scatter(particle_x, particle_y, c='red', s=30, alpha=0.7, label='Particles') |
| | |
| | |
| | self.ax.scatter(best_pos[0], best_pos[1], c='green', s=100, marker='*', label='Global Best') |
| | |
| | self.ax.set_xlabel('X') |
| | self.ax.set_ylabel('Y') |
| | self.ax.set_title(f'3D Function Projection (Z fixed at {fixed_z:.3f})') |
| | self.ax.legend() |
| |
|
| | class PSOApp(QMainWindow): |
| | def __init__(self): |
| | super().__init__() |
| | self.equations = EquationDefinitions.get_equations() |
| | self.current_pso = None |
| | self.current_iteration = 0 |
| | self.timer = QTimer() |
| | self.timer.timeout.connect(self.update_visualization) |
| | |
| | self.init_ui() |
| | |
| | def init_ui(self): |
| | self.setWindowTitle("Particle Swarm Optimization - 20 Equations Solver") |
| | self.setGeometry(100, 100, 1600, 1000) |
| | |
| | |
| | central_widget = QWidget() |
| | self.setCentralWidget(central_widget) |
| | |
| | |
| | main_layout = QHBoxLayout(central_widget) |
| | |
| | |
| | left_panel = QWidget() |
| | left_panel.setMaximumWidth(400) |
| | left_layout = QVBoxLayout(left_panel) |
| | |
| | |
| | equation_group = QGroupBox("Equation Selection") |
| | equation_layout = QVBoxLayout(equation_group) |
| | |
| | self.equation_combo = QComboBox() |
| | self.equation_combo.addItems(self.equations.keys()) |
| | self.equation_combo.currentTextChanged.connect(self.on_equation_changed) |
| | equation_layout.addWidget(QLabel("Select Equation:")) |
| | equation_layout.addWidget(self.equation_combo) |
| | |
| | self.equation_desc = QTextEdit() |
| | self.equation_desc.setMaximumHeight(100) |
| | self.equation_desc.setReadOnly(True) |
| | equation_layout.addWidget(QLabel("Description:")) |
| | equation_layout.addWidget(self.equation_desc) |
| | |
| | left_layout.addWidget(equation_group) |
| | |
| | |
| | params_group = QGroupBox("PSO Parameters") |
| | params_layout = QGridLayout(params_group) |
| | |
| | params_layout.addWidget(QLabel("Particles:"), 0, 0) |
| | self.particles_spin = QSpinBox() |
| | self.particles_spin.setRange(10, 100) |
| | self.particles_spin.setValue(30) |
| | params_layout.addWidget(self.particles_spin, 0, 1) |
| | |
| | params_layout.addWidget(QLabel("Iterations:"), 1, 0) |
| | self.iterations_spin = QSpinBox() |
| | self.iterations_spin.setRange(10, 500) |
| | self.iterations_spin.setValue(100) |
| | params_layout.addWidget(self.iterations_spin, 1, 1) |
| | |
| | params_layout.addWidget(QLabel("Inertia (w):"), 2, 0) |
| | self.w_spin = QDoubleSpinBox() |
| | self.w_spin.setRange(0.1, 1.0) |
| | self.w_spin.setSingleStep(0.1) |
| | self.w_spin.setValue(0.7) |
| | params_layout.addWidget(self.w_spin, 2, 1) |
| | |
| | params_layout.addWidget(QLabel("Cognitive (c1):"), 3, 0) |
| | self.c1_spin = QDoubleSpinBox() |
| | self.c1_spin.setRange(0.1, 2.0) |
| | self.c1_spin.setSingleStep(0.1) |
| | self.c1_spin.setValue(1.4) |
| | params_layout.addWidget(self.c1_spin, 3, 1) |
| | |
| | params_layout.addWidget(QLabel("Social (c2):"), 4, 0) |
| | self.c2_spin = QDoubleSpinBox() |
| | self.c2_spin.setRange(0.1, 2.0) |
| | self.c2_spin.setSingleStep(0.1) |
| | self.c2_spin.setValue(1.4) |
| | params_layout.addWidget(self.c2_spin, 4, 1) |
| | |
| | left_layout.addWidget(params_group) |
| | |
| | |
| | control_group = QGroupBox("Controls") |
| | control_layout = QVBoxLayout(control_group) |
| | |
| | self.run_button = QPushButton("Run PSO") |
| | self.run_button.clicked.connect(self.run_pso) |
| | control_layout.addWidget(self.run_button) |
| | |
| | self.pause_button = QPushButton("Pause") |
| | self.pause_button.clicked.connect(self.toggle_pause) |
| | self.pause_button.setEnabled(False) |
| | control_layout.addWidget(self.pause_button) |
| | |
| | self.step_button = QPushButton("Step") |
| | self.step_button.clicked.connect(self.step_forward) |
| | self.step_button.setEnabled(False) |
| | control_layout.addWidget(self.step_button) |
| | |
| | self.reset_button = QPushButton("Reset") |
| | self.reset_button.clicked.connect(self.reset) |
| | control_layout.addWidget(self.reset_button) |
| | |
| | left_layout.addWidget(control_group) |
| | |
| | |
| | progress_group = QGroupBox("Progress") |
| | progress_layout = QVBoxLayout(progress_group) |
| | |
| | self.progress_bar = QProgressBar() |
| | self.progress_bar.setValue(0) |
| | progress_layout.addWidget(self.progress_bar) |
| | |
| | self.status_label = QLabel("Ready to optimize") |
| | progress_layout.addWidget(self.status_label) |
| | |
| | self.results_text = QTextEdit() |
| | self.results_text.setMaximumHeight(150) |
| | self.results_text.setReadOnly(True) |
| | progress_layout.addWidget(self.results_text) |
| | |
| | left_layout.addWidget(progress_group) |
| | left_layout.addStretch() |
| | |
| | |
| | right_panel = QWidget() |
| | right_layout = QVBoxLayout(right_panel) |
| | |
| | |
| | splitter = QSplitter(Qt.Vertical) |
| | |
| | self.plot_2d = PlotCanvas(self, width=8, height=6, dpi=100, is_3d=False) |
| | self.plot_3d = PlotCanvas(self, width=8, height=6, dpi=100, is_3d=True) |
| | |
| | splitter.addWidget(self.plot_2d) |
| | splitter.addWidget(self.plot_3d) |
| | splitter.setSizes([500, 500]) |
| | |
| | right_layout.addWidget(splitter) |
| | |
| | |
| | main_layout.addWidget(left_panel) |
| | main_layout.addWidget(right_panel) |
| | |
| | |
| | self.on_equation_changed(self.equation_combo.currentText()) |
| | |
| | def on_equation_changed(self, equation_name): |
| | equation_info = self.equations[equation_name] |
| | self.equation_desc.setText(equation_info['description']) |
| | |
| | def run_pso(self): |
| | try: |
| | equation_name = self.equation_combo.currentText() |
| | equation_info = self.equations[equation_name] |
| | |
| | |
| | num_particles = self.particles_spin.value() |
| | max_iterations = self.iterations_spin.value() |
| | w = self.w_spin.value() |
| | c1 = self.c1_spin.value() |
| | c2 = self.c2_spin.value() |
| | |
| | |
| | self.current_pso = PSO( |
| | objective_func=equation_info['func'], |
| | dim=equation_info['dim'], |
| | bounds=equation_info['bounds'], |
| | num_particles=num_particles, |
| | w=w, c1=c1, c2=c2 |
| | ) |
| | |
| | |
| | best_position, best_value = self.current_pso.optimize(max_iterations) |
| | |
| | |
| | self.results_text.setText( |
| | f"Optimization Complete!\n" |
| | f"Best Position: {[f'{x:.6f}' for x in best_position]}\n" |
| | f"Best Value: {best_value:.10f}\n" |
| | f"Equation: {equation_name}" |
| | ) |
| | |
| | |
| | self.current_iteration = 0 |
| | self.progress_bar.setMaximum(max_iterations - 1) |
| | self.update_visualization() |
| | |
| | |
| | self.pause_button.setEnabled(True) |
| | self.step_button.setEnabled(True) |
| | self.run_button.setEnabled(False) |
| | |
| | |
| | self.timer.start(100) |
| | |
| | except Exception as e: |
| | self.results_text.setText(f"Error during optimization: {str(e)}") |
| | |
| | def toggle_pause(self): |
| | if self.timer.isActive(): |
| | self.timer.stop() |
| | self.pause_button.setText("Resume") |
| | else: |
| | self.timer.start(100) |
| | self.pause_button.setText("Pause") |
| | |
| | def step_forward(self): |
| | if self.current_pso and self.current_iteration < len(self.current_pso.history) - 1: |
| | self.current_iteration += 1 |
| | self.update_visualization() |
| | |
| | def reset(self): |
| | self.timer.stop() |
| | self.current_pso = None |
| | self.current_iteration = 0 |
| | self.progress_bar.setValue(0) |
| | self.status_label.setText("Ready to optimize") |
| | self.results_text.clear() |
| | self.pause_button.setEnabled(False) |
| | self.step_button.setEnabled(False) |
| | self.run_button.setEnabled(True) |
| | self.pause_button.setText("Pause") |
| | |
| | |
| | self.plot_2d.ax.clear() |
| | self.plot_3d.ax.clear() |
| | self.plot_2d.draw() |
| | self.plot_3d.draw() |
| | |
| | def update_visualization(self): |
| | if not self.current_pso or self.current_iteration >= len(self.current_pso.history): |
| | self.timer.stop() |
| | self.status_label.setText("Optimization Complete!") |
| | return |
| | |
| | equation_name = self.equation_combo.currentText() |
| | equation_info = self.equations[equation_name] |
| | |
| | try: |
| | |
| | self.plot_2d.plot_optimization(equation_info, self.current_pso.history, self.current_iteration) |
| | |
| | |
| | self.plot_3d.plot_optimization(equation_info, self.current_pso.history, self.current_iteration) |
| | |
| | |
| | self.progress_bar.setValue(self.current_iteration) |
| | self.status_label.setText(f"Iteration {self.current_iteration + 1}/{len(self.current_pso.history)}") |
| | |
| | self.current_iteration += 1 |
| | |
| | if self.current_iteration >= len(self.current_pso.history): |
| | self.timer.stop() |
| | self.status_label.setText("Optimization Complete!") |
| | |
| | except Exception as e: |
| | self.status_label.setText(f"Visualization error: {str(e)}") |
| | self.timer.stop() |
| |
|
| | def main(): |
| | app = QApplication(sys.argv) |
| | app.setStyle('Fusion') |
| | |
| | |
| | font = QFont("Arial", 10) |
| | app.setFont(font) |
| | |
| | window = PSOApp() |
| | window.show() |
| | |
| | sys.exit(app.exec_()) |
| |
|
| | if __name__ == '__main__': |
| | main() |