class Window(QWidget): def __init__(self, parent = None): QWidget.__init__(self, parent) self.setWindowTitle('Simulated Annealing') layout = QVBoxLayout(self) layout.setContentsMargins(0,0,0,0) self.setLayout(layout) # create plotHandler self.plotHandler = PlotHandler(self) layout.addWidget(self.plotHandler.get_widget()) # create step Button self.stepButton = QPushButton(self) self.stepButton.setText('Step') layout.addWidget(self.stepButton) self.stepButton.clicked.connect(self.step) self.runButton = QPushButton(self) self.runButton.setText('Run') layout.addWidget(self.runButton) self.runButton.clicked.connect(self.run) # Evolution algorithm important properties self.algorithm = None self.specimenTemplate = None self.testFunctions = None self.fitnessFunction = None self.actualPopulation = None self.bestPopulation = None self.iteration = 0 # Plot initialization self.initialize_plot() @QtCore.pyqtSlot() def step(self): if self.algorithm is None: self.algorithm = EA.DifferentialEvolution( self.actualPopulation, self.fitnessFunction, self.specimenTemplate, self.updateCallback) # Not needed here # Its interesting that self.actualPopulation is given to algorithm via reference # So all changes inside algorithm are also shown here self.algorithm.step() self.actualPopulation = self.actualPopulation = self.algorithm.population self.plotHandler.updatePopulation(self.actualPopulation) print "Generation {0}".format(self.algorithm.generation) @QtCore.pyqtSlot() def run(self): if self.algorithm is None: self.algorithm = EA.DifferentialEvolution( self.actualPopulation, self.fitnessFunction, self.specimenTemplate, self.updateCallback) self.algorithm.run() def initialize_plot(self): """ Initialization of default plot - adds some data to plot. :return: """ self.fitnessFunction = TF.firstDeJong # raw data x = np.arange(-3, 3, 0.2) y = x z = self.fitnessFunction(np.meshgrid(x, x)) self.plotHandler.updatePlot(x, y, z) self.generate_population(10) @QtCore.pyqtSlot() def generate_population(self, n): """ Generates population with size of N :param n: :return: """ self.specimenTemplate = self.getSpecimenTemplate(-3, 3) self.actualPopulation = PopulationUtils.generate_population( self.specimenTemplate, n, self.fitnessFunction) # Show population self.plotHandler.updatePopulation(self.actualPopulation) def getSpecimenTemplate(self, min_const, max_const, only_integer=False): """ Returns specimen template :param min_const: :param max_const: :param only_integer: :return: """ data_type = 'real' if only_integer: data_type = 'integer' return [(data_type, (min_const, max_const))] * 2 def updateCallback(self, actual_population, best_population): """ Update callback :param actual_population: :param best_population: :return: """ # print 'NEW' # print actual_population self.bestPopulation = best_population # self.actualPopulation = actual_population self.plotHandler.updatePopulation(self.actualPopulation) print 'Iteration {0}'.format(self.iteration) self.iteration += 1
class AppWindow(QMainWindow, Ui_MainWindow): """ Root application widget """ def __init__(self, parent=None): QMainWindow.__init__(self, parent) Ui_MainWindow.__init__(self) self.setupUi(self) # canvas with graph layout = QVBoxLayout(self.graphicsView) layout.setContentsMargins(0, 0, 0, 0) self.graphicsView.setLayout(layout) # create plotHandler self.plotHandler = PlotHandler(self) layout.addWidget(self.plotHandler.get_widget()) self.changeButton.clicked.connect(self.update_plot) self.generateButton.clicked.connect(self.generate_population) # ToolBox with algorithms QtCore.QObject.connect(self.chooseSearchToolBox, QtCore.SIGNAL('currentChanged(int)'), self, QtCore.SLOT('algorithm_change_callback(int)') ) # Run button self.ButtonRun.clicked.connect(self.run_button_callback) # Step Button self.ButtonStep.clicked.connect(self.step_button_callback) # Evolution algorithm important properties self.algorithm = None self.test_functions = None self.fitness_function = None self.actualPopulation = None # Plot initialization self.initialize_plot() def initialize_plot(self): """ Initialize plot and test functions :return: """ self.test_functions = [ tF.firstDeJong, tF.rosenbrocksSaddle, tF.thirdDeJong, tF.forthDeJong, tF.rastrigin, tF.schewefel, tF.griewangkova, tF.sineEnvelope, tF.sineWave, tF.MultiPurposeFnc ] self.update_plot() @QtCore.pyqtSlot() def update_plot(self): """ Updates fitness function surface graph If there is some population - generates new one """ x1 = self.mindoubleSpinBox.value() x2 = self.maxdoubleSpinBox.value() x3 = self.pointsdoubleSpinBox.value() self.fitness_function = self.test_functions[self.chooseFunctionComboBox.currentIndex()] # regenerate population if self.actualPopulation is not None: template = self.get_specimen_template() n = self.numOfSpecimenSpinBox.value() # generate new population self.actualPopulation = PopulationUtils.generate_population( self.get_specimen_template(), n, self.fitness_function ) # Add reference to algorithm and update if self.algorithm is not None: self.algorithm.set_specimen_template(template) self.algorithm.set_population(self.actualPopulation) # surface plot data x = np.arange(x1, x2, x3) y = x z = None if self.fitness_function.__name__ is tF.MultiPurposeFnc.__name__: print 'gooo' z = tF.MultiPurposeFnc.graph_z(x, y) else: z = self.fitness_function(np.meshgrid(x, x)) # Draw all at once self.plotHandler.updatePlot(x, y, z, population=self.actualPopulation) @QtCore.pyqtSlot() def generate_population(self): """ Generate Population and set it :return: """ template = self.get_specimen_template() n = self.numOfSpecimenSpinBox.value() self.actualPopulation = PopulationUtils.generate_population( template, n, self.fitness_function) # Add reference to algorithm if self.algorithm is not None: self.algorithm.set_specimen_template(template) self.algorithm.set_population(self.actualPopulation) # Show population self.plotHandler.updatePopulation(self.actualPopulation) def get_specimen_template(self): """ Generates specimen template according to given constraints :return: """ min_const = self.mindoubleSpinBox.value() max_const = self.maxdoubleSpinBox.value() only_integer = self.intCheckBox.isChecked() data_type = 'real' if only_integer: data_type = 'integer' return [(data_type, (min_const, max_const))] * 2 def update_callback(self, actual_population, best_population, done=False): """ Callback for algorithms to trigger after each iteration :param actual_population: :param best_population: :param done: :return: """ self.actualPopulation = actual_population # TODO: Save best population to log Widget if done: print 'Algorithm finished' # self.actualPopulation = best_population self.plotHandler.updatePopulation(best_population) else: self.plotHandler.updatePopulation(self.actualPopulation) @QtCore.pyqtSlot() def run_button_callback(self): """ Execute algorithm :return: """ if self.algorithm is not None: self.algorithm.run() @QtCore.pyqtSlot() def step_button_callback(self): """ Triggers when step button is clicked :return: """ if self.algorithm is not None: self.algorithm.step() self.plotHandler.updatePopulation(self.algorithm.population) @QtCore.pyqtSlot(int) def algorithm_change_callback(self, index): """ Triggers when algorithm is changed from toolbox :param index: :return: """ if index < (len(INDEX_ALGORITHM)): if INDEX_ALGORITHM[index] is None: print 'None' return self.algorithm = INDEX_ALGORITHM[index](self.actualPopulation, self.fitness_function, self.get_specimen_template(), self.update_callback ) print '{0} - {1} selected '.format(index, INDEX_ALGORITHM[index].__name__) else: return