class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 880) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( MainWindow.sizePolicy().hasHeightForWidth()) MainWindow.setSizePolicy(sizePolicy) MainWindow.setMinimumSize(QtCore.QSize(0, 640)) MainWindow.setAutoFillBackground(True) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.main_frame = QtWidgets.QFrame(self.centralwidget) self.main_frame.setObjectName("main_frame") self.gridLayout_7 = QtWidgets.QGridLayout(self.main_frame) self.gridLayout_7.setObjectName("gridLayout_7") self.data_display_group = QtWidgets.QGroupBox(self.main_frame) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.data_display_group.sizePolicy().hasHeightForWidth()) self.data_display_group.setSizePolicy(sizePolicy) self.data_display_group.setObjectName("data_display_group") self.gridLayout_2 = QtWidgets.QGridLayout(self.data_display_group) self.gridLayout_2.setObjectName("gridLayout_2") self.sweep_value = QtWidgets.QLabel(self.data_display_group) font = QtGui.QFont() font.setFamily("Iosevka Aile") font.setPointSize(20) font.setBold(True) font.setWeight(75) self.sweep_value.setFont(font) self.sweep_value.setScaledContents(False) self.sweep_value.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.sweep_value.setObjectName("sweep_value") self.gridLayout_2.addWidget(self.sweep_value, 5, 2, 1, 1) self.channelA_value = QtWidgets.QLabel(self.data_display_group) palette = QtGui.QPalette() brush = QtGui.QBrush(QtGui.QColor(33, 150, 243)) brush.setStyle(QtCore.Qt.SolidPattern) palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) brush = QtGui.QBrush(QtGui.QColor(33, 150, 243)) brush.setStyle(QtCore.Qt.SolidPattern) palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush) brush = QtGui.QBrush(QtGui.QColor(33, 150, 243)) brush.setStyle(QtCore.Qt.SolidPattern) palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) brush = QtGui.QBrush(QtGui.QColor(33, 150, 243)) brush.setStyle(QtCore.Qt.SolidPattern) palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush) brush = QtGui.QBrush(QtGui.QColor(127, 127, 127)) brush.setStyle(QtCore.Qt.SolidPattern) palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) brush = QtGui.QBrush(QtGui.QColor(127, 127, 127)) brush.setStyle(QtCore.Qt.SolidPattern) palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush) self.channelA_value.setPalette(palette) font = QtGui.QFont() font.setFamily("Iosevka Aile") font.setPointSize(20) font.setBold(True) font.setWeight(75) self.channelA_value.setFont(font) self.channelA_value.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.channelA_value.setObjectName("channelA_value") self.gridLayout_2.addWidget(self.channelA_value, 3, 1, 1, 2) self.channelB_label = QtWidgets.QLabel(self.data_display_group) font = QtGui.QFont() font.setPointSize(20) self.channelB_label.setFont(font) self.channelB_label.setObjectName("channelB_label") self.gridLayout_2.addWidget(self.channelB_label, 4, 0, 1, 1) self.channelB_value = QtWidgets.QLabel(self.data_display_group) palette = QtGui.QPalette() brush = QtGui.QBrush(QtGui.QColor(255, 82, 82)) brush.setStyle(QtCore.Qt.SolidPattern) palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) brush = QtGui.QBrush(QtGui.QColor(255, 82, 82)) brush.setStyle(QtCore.Qt.SolidPattern) palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush) brush = QtGui.QBrush(QtGui.QColor(255, 82, 82)) brush.setStyle(QtCore.Qt.SolidPattern) palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) brush = QtGui.QBrush(QtGui.QColor(255, 82, 82)) brush.setStyle(QtCore.Qt.SolidPattern) palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush) brush = QtGui.QBrush(QtGui.QColor(127, 127, 127)) brush.setStyle(QtCore.Qt.SolidPattern) palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) brush = QtGui.QBrush(QtGui.QColor(127, 127, 127)) brush.setStyle(QtCore.Qt.SolidPattern) palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush) self.channelB_value.setPalette(palette) font = QtGui.QFont() font.setFamily("Iosevka Aile") font.setPointSize(20) font.setBold(True) font.setWeight(75) self.channelB_value.setFont(font) self.channelB_value.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.channelB_value.setObjectName("channelB_value") self.gridLayout_2.addWidget(self.channelB_value, 4, 1, 1, 2) self.dec_label = QtWidgets.QLabel(self.data_display_group) font = QtGui.QFont() font.setPointSize(20) self.dec_label.setFont(font) self.dec_label.setObjectName("dec_label") self.gridLayout_2.addWidget(self.dec_label, 2, 0, 1, 1) self.dec_value = QtWidgets.QLabel(self.data_display_group) font = QtGui.QFont() font.setFamily("Iosevka Aile") font.setPointSize(20) font.setBold(True) font.setWeight(75) self.dec_value.setFont(font) self.dec_value.setScaledContents(False) self.dec_value.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.dec_value.setObjectName("dec_value") self.gridLayout_2.addWidget(self.dec_value, 2, 1, 1, 2) self.ra_label = QtWidgets.QLabel(self.data_display_group) font = QtGui.QFont() font.setPointSize(20) self.ra_label.setFont(font) self.ra_label.setObjectName("ra_label") self.gridLayout_2.addWidget(self.ra_label, 1, 0, 1, 1) self.ra_value = QtWidgets.QLabel(self.data_display_group) font = QtGui.QFont() font.setFamily("Iosevka Aile") font.setPointSize(20) font.setBold(True) font.setWeight(75) self.ra_value.setFont(font) self.ra_value.setScaledContents(False) self.ra_value.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.ra_value.setObjectName("ra_value") self.gridLayout_2.addWidget(self.ra_value, 1, 1, 1, 2) self.sweep_label = QtWidgets.QLabel(self.data_display_group) font = QtGui.QFont() font.setPointSize(20) self.sweep_label.setFont(font) self.sweep_label.setObjectName("sweep_label") self.gridLayout_2.addWidget(self.sweep_label, 5, 0, 1, 1) self.channelA_label = QtWidgets.QLabel(self.data_display_group) font = QtGui.QFont() font.setPointSize(20) self.channelA_label.setFont(font) self.channelA_label.setObjectName("channelA_label") self.gridLayout_2.addWidget(self.channelA_label, 3, 0, 1, 1) self.gridLayout_7.addWidget(self.data_display_group, 1, 0, 1, 1) self.stripchart_control_group = QtWidgets.QGroupBox(self.main_frame) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.stripchart_control_group.sizePolicy().hasHeightForWidth()) self.stripchart_control_group.setSizePolicy(sizePolicy) self.stripchart_control_group.setObjectName("stripchart_control_group") self.gridLayout_4 = QtWidgets.QGridLayout( self.stripchart_control_group) self.gridLayout_4.setObjectName("gridLayout_4") self.frame_2 = QtWidgets.QFrame(self.stripchart_control_group) self.frame_2.setObjectName("frame_2") self.gridLayout_3 = QtWidgets.QGridLayout(self.frame_2) self.gridLayout_3.setContentsMargins(-1, 0, -1, 0) self.gridLayout_3.setObjectName("gridLayout_3") self.stripchart_faster_label = QtWidgets.QLabel(self.frame_2) self.stripchart_faster_label.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) self.stripchart_faster_label.setObjectName("stripchart_faster_label") self.gridLayout_3.addWidget(self.stripchart_faster_label, 0, 2, 1, 1) self.stripchart_speed_slider = QtWidgets.QSlider(self.frame_2) self.stripchart_speed_slider.setMaximum(6) self.stripchart_speed_slider.setProperty("value", 3) self.stripchart_speed_slider.setOrientation(QtCore.Qt.Horizontal) self.stripchart_speed_slider.setTickPosition( QtWidgets.QSlider.TicksBothSides) self.stripchart_speed_slider.setTickInterval(1) self.stripchart_speed_slider.setObjectName("stripchart_speed_slider") self.gridLayout_3.addWidget(self.stripchart_speed_slider, 0, 1, 1, 1) self.stripchart_slower_label = QtWidgets.QLabel(self.frame_2) self.stripchart_slower_label.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) self.stripchart_slower_label.setObjectName("stripchart_slower_label") self.gridLayout_3.addWidget(self.stripchart_slower_label, 0, 0, 1, 1) self.gridLayout_4.addWidget(self.frame_2, 0, 0, 1, 4) self.frame = QtWidgets.QFrame(self.stripchart_control_group) self.frame.setObjectName("frame") self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame) self.horizontalLayout.setContentsMargins(0, 0, 0, 0) self.horizontalLayout.setObjectName("horizontalLayout") self.toggle_channel_button = QtWidgets.QPushButton(self.frame) self.toggle_channel_button.setObjectName("toggle_channel_button") self.horizontalLayout.addWidget(self.toggle_channel_button) self.chart_clear_button = QtWidgets.QPushButton(self.frame) self.chart_clear_button.setObjectName("chart_clear_button") self.horizontalLayout.addWidget(self.chart_clear_button) self.gridLayout_4.addWidget(self.frame, 3, 0, 1, 4) self.gridLayout_7.addWidget(self.stripchart_control_group, 2, 0, 1, 1) self.message_group_box = QtWidgets.QGroupBox(self.main_frame) self.message_group_box.setObjectName("message_group_box") self.gridLayout_5 = QtWidgets.QGridLayout(self.message_group_box) self.gridLayout_5.setObjectName("gridLayout_5") self.refresh_label = QtWidgets.QLabel(self.message_group_box) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.refresh_label.sizePolicy().hasHeightForWidth()) self.refresh_label.setSizePolicy(sizePolicy) self.refresh_label.setStyleSheet("color: #7a7c7e") self.refresh_label.setObjectName("refresh_label") self.gridLayout_5.addWidget(self.refresh_label, 2, 0, 1, 1) self.refresh_value = QtWidgets.QLabel(self.message_group_box) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.refresh_value.sizePolicy().hasHeightForWidth()) self.refresh_value.setSizePolicy(sizePolicy) font = QtGui.QFont() font.setFamily("Iosevka Aile") font.setBold(True) font.setWeight(75) self.refresh_value.setFont(font) self.refresh_value.setStyleSheet("color: #7a7c7e") self.refresh_value.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.refresh_value.setObjectName("refresh_value") self.gridLayout_5.addWidget(self.refresh_value, 2, 1, 1, 1) self.progressBar = QtWidgets.QProgressBar(self.message_group_box) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.progressBar.sizePolicy().hasHeightForWidth()) self.progressBar.setSizePolicy(sizePolicy) font = QtGui.QFont() font.setFamily("Iosevka Aile") font.setPointSize(16) self.progressBar.setFont(font) self.progressBar.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) self.progressBar.setInvertedAppearance(False) self.progressBar.setObjectName("progressBar") self.gridLayout_5.addWidget(self.progressBar, 1, 0, 1, 2) self.message_label = QtWidgets.QLabel(self.message_group_box) font = QtGui.QFont() font.setPointSize(20) self.message_label.setFont(font) self.message_label.setObjectName("message_label") self.gridLayout_5.addWidget(self.message_label, 0, 0, 1, 2) self.gridLayout_7.addWidget(self.message_group_box, 0, 0, 1, 1) self.console_background = QtWidgets.QFrame(self.main_frame) self.console_background.setObjectName("console_background") self.gridLayout_11 = QtWidgets.QGridLayout(self.console_background) self.gridLayout_11.setContentsMargins(0, -1, 0, -1) self.gridLayout_11.setObjectName("gridLayout_11") self.console_inner_frame_2 = QtWidgets.QFrame(self.console_background) self.console_inner_frame_2.setStyleSheet( "background: black; border-radius: 5px") self.console_inner_frame_2.setObjectName("console_inner_frame_2") self.gridLayout_12 = QtWidgets.QGridLayout(self.console_inner_frame_2) self.gridLayout_12.setObjectName("gridLayout_12") self.console_label = QtWidgets.QLabel(self.console_inner_frame_2) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.console_label.sizePolicy().hasHeightForWidth()) self.console_label.setSizePolicy(sizePolicy) font = QtGui.QFont() font.setFamily("Iosevka Aile") font.setPointSize(10) font.setBold(True) font.setWeight(75) self.console_label.setFont(font) self.console_label.setStyleSheet("color: #0f0") self.console_label.setAlignment(QtCore.Qt.AlignBottom | QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft) self.console_label.setObjectName("console_label") self.gridLayout_12.addWidget(self.console_label, 0, 0, 1, 1) self.dec_view = QtWidgets.QGraphicsView(self.console_inner_frame_2) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.dec_view.sizePolicy().hasHeightForWidth()) self.dec_view.setSizePolicy(sizePolicy) self.dec_view.setStyleSheet("background: transparent") self.dec_view.setFrameShape(QtWidgets.QFrame.NoFrame) self.dec_view.setFrameShadow(QtWidgets.QFrame.Plain) self.dec_view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.dec_view.setHorizontalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) self.dec_view.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.TextAntialiasing) self.dec_view.setObjectName("dec_view") self.gridLayout_12.addWidget(self.dec_view, 0, 1, 1, 1) self.gridLayout_11.addWidget(self.console_inner_frame_2, 0, 0, 1, 1) self.gridLayout_7.addWidget(self.console_background, 3, 0, 1, 1) self.output_frame = QtWidgets.QFrame(self.main_frame) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.output_frame.sizePolicy().hasHeightForWidth()) self.output_frame.setSizePolicy(sizePolicy) self.output_frame.setMinimumSize(QtCore.QSize(360, 0)) self.output_frame.setObjectName("output_frame") self.gridLayout_10 = QtWidgets.QGridLayout(self.output_frame) self.gridLayout_10.setContentsMargins(0, 0, 0, 0) self.gridLayout_10.setObjectName("gridLayout_10") self.stripchart = QChartView(self.output_frame) self.stripchart.setFrameShape(QtWidgets.QFrame.NoFrame) self.stripchart.setFrameShadow(QtWidgets.QFrame.Plain) self.stripchart.setObjectName("stripchart") self.gridLayout_10.addWidget(self.stripchart, 0, 0, 2, 2) self.gridLayout_7.addWidget(self.output_frame, 0, 1, 4, 1) self.gridLayout.addWidget(self.main_frame, 0, 0, 1, 1) self.testing_frame = QtWidgets.QFrame(self.centralwidget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.testing_frame.sizePolicy().hasHeightForWidth()) self.testing_frame.setSizePolicy(sizePolicy) self.testing_frame.setMinimumSize(QtCore.QSize(0, 180)) self.testing_frame.setObjectName("testing_frame") self.gridLayout_8 = QtWidgets.QGridLayout(self.testing_frame) self.gridLayout_8.setContentsMargins(-1, 0, -1, -1) self.gridLayout_8.setObjectName("gridLayout_8") self.dec_group_box = QtWidgets.QGroupBox(self.testing_frame) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.dec_group_box.sizePolicy().hasHeightForWidth()) self.dec_group_box.setSizePolicy(sizePolicy) self.dec_group_box.setObjectName("dec_group_box") self.gridLayout_9 = QtWidgets.QGridLayout(self.dec_group_box) self.gridLayout_9.setObjectName("gridLayout_9") self.north_label = QtWidgets.QLabel(self.dec_group_box) self.north_label.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) self.north_label.setObjectName("north_label") self.gridLayout_9.addWidget(self.north_label, 0, 1, 1, 1) self.south_label = QtWidgets.QLabel(self.dec_group_box) self.south_label.setAlignment(QtCore.Qt.AlignBottom | QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft) self.south_label.setObjectName("south_label") self.gridLayout_9.addWidget(self.south_label, 1, 1, 1, 1) self.declination_slider = QtWidgets.QSlider(self.dec_group_box) self.declination_slider.setMinimum(-99) self.declination_slider.setMaximum(99) self.declination_slider.setSingleStep(1) self.declination_slider.setProperty("value", 0) self.declination_slider.setTickInterval(20) self.declination_slider.setObjectName("declination_slider") self.gridLayout_9.addWidget(self.declination_slider, 0, 0, 2, 1) self.dec_auto_check_box = QtWidgets.QCheckBox(self.dec_group_box) self.dec_auto_check_box.setChecked(True) self.dec_auto_check_box.setObjectName("dec_auto_check_box") self.gridLayout_9.addWidget(self.dec_auto_check_box, 2, 0, 1, 2) self.gridLayout_8.addWidget(self.dec_group_box, 0, 1, 1, 1) self.signal_group_box = QtWidgets.QGroupBox(self.testing_frame) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.signal_group_box.sizePolicy().hasHeightForWidth()) self.signal_group_box.setSizePolicy(sizePolicy) self.signal_group_box.setObjectName("signal_group_box") self.gridLayout_6 = QtWidgets.QGridLayout(self.signal_group_box) self.gridLayout_6.setObjectName("gridLayout_6") self.variance_dial = QtWidgets.QDial(self.signal_group_box) self.variance_dial.setMinimum(0) self.variance_dial.setMaximum(16) self.variance_dial.setPageStep(4) self.variance_dial.setProperty("value", 4) self.variance_dial.setWrapping(False) self.variance_dial.setNotchTarget(1.0) self.variance_dial.setNotchesVisible(True) self.variance_dial.setObjectName("variance_dial") self.gridLayout_6.addWidget(self.variance_dial, 1, 0, 1, 1) self.variance_label = QtWidgets.QLabel(self.signal_group_box) self.variance_label.setAlignment(QtCore.Qt.AlignCenter) self.variance_label.setObjectName("variance_label") self.gridLayout_6.addWidget(self.variance_label, 3, 0, 1, 1) self.noise_label = QtWidgets.QLabel(self.signal_group_box) self.noise_label.setAlignment(QtCore.Qt.AlignCenter) self.noise_label.setObjectName("noise_label") self.gridLayout_6.addWidget(self.noise_label, 3, 3, 1, 1) self.polarization_label = QtWidgets.QLabel(self.signal_group_box) self.polarization_label.setAlignment(QtCore.Qt.AlignCenter) self.polarization_label.setObjectName("polarization_label") self.gridLayout_6.addWidget(self.polarization_label, 3, 2, 1, 1) self.polarization_dial = QtWidgets.QDial(self.signal_group_box) self.polarization_dial.setMinimum(0) self.polarization_dial.setMaximum(16) self.polarization_dial.setPageStep(4) self.polarization_dial.setProperty("value", 4) self.polarization_dial.setWrapping(False) self.polarization_dial.setNotchTarget(1.0) self.polarization_dial.setNotchesVisible(True) self.polarization_dial.setObjectName("polarization_dial") self.gridLayout_6.addWidget(self.polarization_dial, 1, 2, 1, 1) self.noise_dial = QtWidgets.QDial(self.signal_group_box) self.noise_dial.setMinimum(0) self.noise_dial.setMaximum(16) self.noise_dial.setPageStep(4) self.noise_dial.setProperty("value", 4) self.noise_dial.setWrapping(False) self.noise_dial.setNotchTarget(1.0) self.noise_dial.setNotchesVisible(True) self.noise_dial.setObjectName("noise_dial") self.gridLayout_6.addWidget(self.noise_dial, 1, 3, 1, 1) self.calibration_check_box = QtWidgets.QCheckBox(self.signal_group_box) self.calibration_check_box.setObjectName("calibration_check_box") self.gridLayout_6.addWidget(self.calibration_check_box, 1, 4, 3, 1) self.gridLayout_8.addWidget(self.signal_group_box, 0, 0, 1, 1) self.gridLayout.addWidget(self.testing_frame, 1, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 43)) self.menubar.setObjectName("menubar") self.menuCalibration = QtWidgets.QMenu(self.menubar) self.menuCalibration.setObjectName("menuCalibration") self.menuFile = QtWidgets.QMenu(self.menubar) self.menuFile.setObjectName("menuFile") self.menuMode = QtWidgets.QMenu(self.menubar) self.menuMode.setObjectName("menuMode") self.menuObservation = QtWidgets.QMenu(self.menubar) self.menuObservation.setObjectName("menuObservation") MainWindow.setMenuBar(self.menubar) self.actionRA = QtWidgets.QAction(MainWindow) self.actionRA.setObjectName("actionRA") self.actionDec = QtWidgets.QAction(MainWindow) self.actionDec.setObjectName("actionDec") self.actionSurvey = QtWidgets.QAction(MainWindow) self.actionSurvey.setObjectName("actionSurvey") self.actionInfo = QtWidgets.QAction(MainWindow) self.actionInfo.setObjectName("actionInfo") self.actionQuit = QtWidgets.QAction(MainWindow) self.actionQuit.setObjectName("actionQuit") self.actionHelp = QtWidgets.QAction(MainWindow) self.actionHelp.setEnabled(False) self.actionHelp.setObjectName("actionHelp") self.actionScan = QtWidgets.QAction(MainWindow) self.actionScan.setObjectName("actionScan") self.actionSpectrum = QtWidgets.QAction(MainWindow) self.actionSpectrum.setObjectName("actionSpectrum") self.actionNormal = QtWidgets.QAction(MainWindow) self.actionNormal.setCheckable(True) self.actionNormal.setObjectName("actionNormal") self.actionTesting = QtWidgets.QAction(MainWindow) self.actionTesting.setCheckable(True) self.actionTesting.setObjectName("actionTesting") self.actionLegacy = QtWidgets.QAction(MainWindow) self.actionLegacy.setCheckable(True) self.actionLegacy.setObjectName("actionLegacy") self.actionGetInfo = QtWidgets.QAction(MainWindow) self.actionGetInfo.setEnabled(False) self.actionGetInfo.setObjectName("actionGetInfo") self.menuCalibration.addAction(self.actionRA) self.menuCalibration.addAction(self.actionDec) self.menuFile.addAction(self.actionHelp) self.menuFile.addAction(self.actionInfo) self.menuFile.addSeparator() self.menuFile.addAction(self.actionQuit) self.menuMode.addAction(self.actionNormal) self.menuMode.addAction(self.actionTesting) self.menuMode.addSeparator() self.menuMode.addAction(self.actionLegacy) self.menuObservation.addAction(self.actionScan) self.menuObservation.addAction(self.actionSurvey) self.menuObservation.addAction(self.actionSpectrum) self.menuObservation.addSeparator() self.menuObservation.addAction(self.actionGetInfo) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuObservation.menuAction()) self.menubar.addAction(self.menuCalibration.menuAction()) self.menubar.addAction(self.menuMode.menuAction()) self.retranslateUi(MainWindow) self.actionQuit.triggered.connect(MainWindow.close) QtCore.QMetaObject.connectSlotsByName(MainWindow) MainWindow.setTabOrder(self.stripchart_speed_slider, self.chart_clear_button) MainWindow.setTabOrder(self.chart_clear_button, self.dec_view) MainWindow.setTabOrder(self.dec_view, self.stripchart) MainWindow.setTabOrder(self.stripchart, self.variance_dial) MainWindow.setTabOrder(self.variance_dial, self.polarization_dial) MainWindow.setTabOrder(self.polarization_dial, self.noise_dial) MainWindow.setTabOrder(self.noise_dial, self.calibration_check_box) MainWindow.setTabOrder(self.calibration_check_box, self.declination_slider) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.data_display_group.setTitle(_translate("MainWindow", "Data")) self.sweep_value.setText(_translate("MainWindow", "n/a")) self.channelA_value.setText(_translate("MainWindow", "0.0000V")) self.channelB_label.setText(_translate("MainWindow", "Channel B:")) self.channelB_value.setText(_translate("MainWindow", "0.0000V")) self.dec_label.setText(_translate("MainWindow", "Declination:")) self.dec_value.setText(_translate("MainWindow", "0.0000deg")) self.ra_label.setText(_translate("MainWindow", "Right Ascension:")) self.ra_value.setText(_translate("MainWindow", "00:00:00")) self.sweep_label.setText(_translate("MainWindow", "Sweep:")) self.channelA_label.setText(_translate("MainWindow", "Channel A:")) self.stripchart_control_group.setTitle( _translate("MainWindow", "Strip chart")) self.stripchart_faster_label.setText(_translate( "MainWindow", "Faster")) self.stripchart_slower_label.setText(_translate( "MainWindow", "Slower")) self.toggle_channel_button.setText( _translate("MainWindow", "Toggle Channels")) self.chart_clear_button.setText(_translate("MainWindow", "Clear Chart")) self.message_group_box.setTitle(_translate("MainWindow", "Message")) self.refresh_label.setText(_translate("MainWindow", "Refresh rate:")) self.refresh_value.setText(_translate("MainWindow", "0.00Hz")) self.message_label.setText(_translate("MainWindow", "...")) self.console_label.setText(_translate("MainWindow", ">>>")) self.dec_group_box.setTitle(_translate("MainWindow", "Declinometer")) self.north_label.setText(_translate("MainWindow", "+")) self.south_label.setText(_translate("MainWindow", "-")) self.dec_auto_check_box.setText(_translate("MainWindow", "Auto")) self.signal_group_box.setTitle(_translate("MainWindow", "Signal")) self.variance_label.setText(_translate("MainWindow", "Variance")) self.noise_label.setText(_translate("MainWindow", "Interference")) self.polarization_label.setText( _translate("MainWindow", "Polarization")) self.calibration_check_box.setText( _translate("MainWindow", "Calibration")) self.menuCalibration.setTitle(_translate("MainWindow", "Calibrate")) self.menuFile.setTitle(_translate("MainWindow", "File")) self.menuMode.setTitle(_translate("MainWindow", "Mode")) self.menuObservation.setTitle(_translate("MainWindow", "Observation")) self.actionRA.setText(_translate("MainWindow", "RA...")) self.actionRA.setShortcut(_translate("MainWindow", "Ctrl+R")) self.actionDec.setText(_translate("MainWindow", "Dec...")) self.actionDec.setShortcut(_translate("MainWindow", "Ctrl+D")) self.actionSurvey.setText(_translate("MainWindow", "New Survey...")) self.actionSurvey.setShortcut(_translate("MainWindow", "Ctrl+2")) self.actionInfo.setText(_translate("MainWindow", "Credits...")) self.actionQuit.setText(_translate("MainWindow", "Exit")) self.actionHelp.setText(_translate("MainWindow", "Help...")) self.actionScan.setText(_translate("MainWindow", "New Scan...")) self.actionScan.setShortcut(_translate("MainWindow", "Ctrl+1")) self.actionSpectrum.setText(_translate("MainWindow", "New Spectrum...")) self.actionSpectrum.setShortcut(_translate("MainWindow", "Ctrl+3")) self.actionNormal.setText(_translate("MainWindow", "Normal")) self.actionNormal.setShortcut(_translate("MainWindow", "Ctrl+N")) self.actionTesting.setText(_translate("MainWindow", "Testing")) self.actionTesting.setShortcut(_translate("MainWindow", "Ctrl+T")) self.actionLegacy.setText(_translate("MainWindow", "Legacy")) self.actionGetInfo.setText(_translate("MainWindow", "Get Info...")) self.actionGetInfo.setShortcut(_translate("MainWindow", "Ctrl+I"))
class Ui_MainWindow(QtWidgets.QMainWindow): def setupUi(self): self.setObjectName("MainWindow") self.resize(600, 830) self.setWindowTitle("GA - Queens") self.centralwidget = QtWidgets.QWidget(self) self.centralwidget.setObjectName("centralwidget") self.frameWorld = MyQFrame(self.centralwidget) self.frameWorld.img = QPixmap(1000, 1000) self.frameWorld.setGeometry(QtCore.QRect(10, 10, 400, 400)) self.frameWorld.setFrameShape(QtWidgets.QFrame.Box) self.frameWorld.setFrameShadow(QtWidgets.QFrame.Sunken) self.frameWorld.setObjectName("frameWorld") self.frameChart = QChartView(self.centralwidget) self.frameChart.setGeometry(QtCore.QRect(10, 420, 400, 400)) self.frameChart.setFrameShape(QtWidgets.QFrame.Box) self.frameChart.setFrameShadow(QtWidgets.QFrame.Sunken) self.frameChart.setRenderHint(QPainter.Antialiasing) self.frameChart.setObjectName("frameChart") self.gaParams = QtWidgets.QGroupBox(self.centralwidget) self.gaParams.setGeometry(QtCore.QRect(430, 10, 161, 171)) self.gaParams.setObjectName("gaParams") self.gaParams.setTitle("GA parameters") self.label1 = QtWidgets.QLabel(self.gaParams) self.label1.setGeometry(QtCore.QRect(10, 20, 61, 16)) self.label1.setObjectName("label1") self.label1.setText("Population:") self.label2 = QtWidgets.QLabel(self.gaParams) self.label2.setGeometry(QtCore.QRect(10, 50, 47, 16)) self.label2.setObjectName("label2") self.label2.setText("Mutation:") self.label3 = QtWidgets.QLabel(self.gaParams) self.label3.setGeometry(QtCore.QRect(10, 80, 81, 16)) self.label3.setObjectName("label3") self.label3.setText("Elite members:") self.label4 = QtWidgets.QLabel(self.gaParams) self.label4.setGeometry(QtCore.QRect(10, 110, 91, 16)) self.label4.setObjectName("label4") self.label4.setText("No. generations:") self.cbxPermutation = QtWidgets.QCheckBox(self.gaParams) self.cbxPermutation.setGeometry(QtCore.QRect(35, 140, 91, 17)) self.cbxPermutation.setObjectName("cbxPermutation") self.cbxPermutation.setText("Permutation") self.tbxPopulation = QtWidgets.QLineEdit(self.gaParams) self.tbxPopulation.setGeometry(QtCore.QRect(100, 20, 51, 20)) self.tbxPopulation.setObjectName("tbxPopulation") self.tbxMutation = QtWidgets.QLineEdit(self.gaParams) self.tbxMutation.setGeometry(QtCore.QRect(100, 50, 51, 20)) self.tbxMutation.setObjectName("tbxMutation") self.tbxElite = QtWidgets.QLineEdit(self.gaParams) self.tbxElite.setGeometry(QtCore.QRect(100, 80, 51, 20)) self.tbxElite.setObjectName("tbxElite") self.tbxGenerations = QtWidgets.QLineEdit(self.gaParams) self.tbxGenerations.setGeometry(QtCore.QRect(100, 110, 51, 20)) self.tbxGenerations.setObjectName("tbxGenerations") self.label5 = QtWidgets.QLabel(self.centralwidget) self.label5.setGeometry(QtCore.QRect(440, 190, 61, 16)) self.label5.setObjectName("label5") self.label5.setText("No. queens:") self.tbxNoQueens = QtWidgets.QLineEdit(self.centralwidget) self.tbxNoQueens.setGeometry(QtCore.QRect(510, 190, 51, 20)) self.tbxNoQueens.setObjectName("tbxNoQueens") self.cbxNoVis = QtWidgets.QCheckBox(self.centralwidget) self.cbxNoVis.setGeometry(QtCore.QRect(420, 215, 170, 17)) self.cbxNoVis.setObjectName("cbxNoVis") self.cbxNoVis.setText("No visualization per generation") self.btnStart = QtWidgets.QPushButton(self.centralwidget) self.btnStart.setGeometry(QtCore.QRect(430, 250, 75, 23)) self.btnStart.setObjectName("btnStart") self.btnStart.setText("Start") self.btnStop = QtWidgets.QPushButton(self.centralwidget) self.btnStop.setEnabled(False) self.btnStop.setGeometry(QtCore.QRect(510, 250, 75, 23)) self.btnStop.setObjectName("btnStop") self.btnStop.setText("Stop") self.btnSaveWorld = QtWidgets.QPushButton(self.centralwidget) self.btnSaveWorld.setGeometry(QtCore.QRect(430, 370, 121, 41)) self.btnSaveWorld.setObjectName("btnSaveWorld") self.btnSaveWorld.setText("Save world as image") self.btnSaveChart = QtWidgets.QPushButton(self.centralwidget) self.btnSaveChart.setGeometry(QtCore.QRect(430, 730, 121, 41)) self.btnSaveChart.setObjectName("btnSaveChart") self.btnSaveChart.setText("Save chart as image") self.btnSaveChartSeries = QtWidgets.QPushButton(self.centralwidget) self.btnSaveChartSeries.setGeometry(QtCore.QRect(430, 780, 121, 41)) self.btnSaveChartSeries.setObjectName("btnSaveChartSeries") self.btnSaveChartSeries.setText("Save chart as series") self.setCentralWidget(self.centralwidget) QtCore.QMetaObject.connectSlotsByName(self) #Connect events self.btnStart.clicked.connect(self.btnStart_Click) self.btnStop.clicked.connect(self.btnStop_Click) self.btnSaveWorld.clicked.connect(self.btnSaveWorld_Click) self.btnSaveChart.clicked.connect(self.btnSaveChart_CLick) self.btnSaveChartSeries.clicked.connect(self.btnSaveChartSeries_Click) #Set default GA variables self.tbxNoQueens.insert(str(NO_QUEENS)) self.tbxGenerations.insert(str(NGEN)) self.tbxPopulation.insert(str(POP_SIZE)) self.tbxMutation.insert(str(MUTPB)) self.tbxElite.insert(str(NELT)) self.new_image = QPixmap(1000, 1000) def btnStart_Click(self): global success # Number of times when fitness function reached 0 -- Added by Denis Lazor global generations # Number of times when fitness function reached 0 -- Added by Denis Lazor global combination_series # List of lists containing min_series of 5 correct results -- Added by Denis Lazor global parameter_name # Name of parameter used for writing its data to .csv file -- Added by Denis Lazor global ELITE_SIZES global BOARD_SIZES global POPULATION_SIZES global MUTATION_SIZES # Checking if files are empty or not -- Added by Denis Lazor csv_contains = os.stat("graphs_csv/original_.csv").st_size != 0 csv_contains_permutation = os.stat( "graphs_csv/original_permutation.csv").st_size != 0 permutation_checked = self.cbxPermutation.isChecked() # Clearing non empty files if we are trying to write to them -- Added by Denis Lazor if csv_contains_permutation and permutation_checked: clear_all_csv("p") if csv_contains and not permutation_checked: clear_all_csv("np") BOARD_SIZES = [12, 24] n = 5000 # Automation for all necessary combinations -- Added by Denis Lazor for b in BOARD_SIZES: # Because we use slicing we need to restore parameters lists after changing board size POPULATION_SIZES = [50, 100, 200] MUTATION_SIZES = [0.04, 0.08, 0.16] ELITE_SIZES = [4, 8, 16] for p in POPULATION_SIZES: for m in MUTATION_SIZES: for e in ELITE_SIZES: success = 0 trials = 0 # Number of tries needed to find 5 'correct' results -- Added by Denis Lazor while success < 5: # Doing same combination till we get 5 'correct' results -- Added by Denis Lazor trials = trials + 1 # Set global variables global stop_evolution global q_min_series global q_max_series global q_avg_series stop_evolution = False q_min_series.clear() q_max_series.clear() q_avg_series.clear() # Set global variables from information on UI global NO_QUEENS global NGEN global POP_SIZE global MUTPB global NELT NO_QUEENS = b NGEN = n POP_SIZE = p MUTPB = m NELT = e # Painting chess table self.img = QPixmap(1000, 1000) self.img.fill() painter = QPainter(self.img) painter.setPen(QPen(Qt.black, 10, Qt.SolidLine)) width = 1000 / NO_QUEENS cur_width = 0 for i in range( NO_QUEENS + 1 ): # +1 in order to draw the last line as well painter.drawLine(cur_width, 0, cur_width, 1000) painter.drawLine(0, cur_width, 1000, cur_width) cur_width += width painter.end() self.frameWorld.img = self.img # Redrawing frames self.frameWorld.repaint() app.processEvents() ####Initialize deap GA objects#### # Make creator that minimize. If it would be 1.0 instead od -1.0 than it would be maxmize creator.create("FitnessMin", base.Fitness, weights=(-1.0, )) # Create an individual (a blueprint for cromosomes) as a list with a specified fitness type creator.create("Individual", list, fitness=creator.FitnessMin) # Create base toolbox for finishing creation of a individual (cromosome) self.toolbox = base.Toolbox() # Define what type of data (number, gene) will it be in the cromosome if self.cbxPermutation.isChecked(): # Permutation coding self.toolbox.register("indices", random.sample, range(NO_QUEENS), NO_QUEENS) # initIterate requires that the generator of genes (such as random.sample) generates an iterable (a list) variable self.toolbox.register("individual", tools.initIterate, creator.Individual, self.toolbox.indices) else: # Standard coding self.toolbox.register( "attr_int", random.randint, 0, NO_QUEENS - 1 ) # number in cromosome is from 0 till IND_SIZE - 1 # Initialization procedure (initRepeat) for the cromosome. For the individual to be completed we need to run initRepeat for the amaout of genes the cromosome includes self.toolbox.register("individual", tools.initRepeat, creator.Individual, self.toolbox.attr_int, n=NO_QUEENS) # Create a population of individuals (cromosomes). The population is then created by toolbox.population(n=300) where 'n' is the number of cromosomes in population self.toolbox.register("population", tools.initRepeat, list, self.toolbox.individual) # Register evaluation function self.toolbox.register("evaluate", evaluateInd) # Register what genetic operators to use if self.cbxPermutation.isChecked(): # Permutation coding self.toolbox.register( "mate", tools.cxUniformPartialyMatched, indpb=0.2 ) # Use uniform recombination for permutation coding self.toolbox.register("mutate", tools.mutShuffleIndexes, indpb=0.2) else: # Standard coding self.toolbox.register( "mate", tools.cxTwoPoint ) # Use two point recombination self.toolbox.register( "mutate", tools.mutUniformInt, low=0, up=NO_QUEENS - 1, indpb=0.2) # 20% that the gene will change self.toolbox.register( "select", tools.selTournament, tournsize=3) # Use tournament selection ################################## # Generate initial poplation. Will be a member variable so we can easely pass everything to new thread self.pop = self.toolbox.population(n=POP_SIZE) # Evaluate initial population, we map() the evaluation function to every individual and then assign their respective fitness, map runs evaluate function for each individual in pop fitnesses = list( map(self.toolbox.evaluate, self.pop)) for ind, fit in zip(self.pop, fitnesses): ind.fitness.values = fit # Assign calcualted fitness value to individuals # Extracting all the fitnesses of all individuals in a population so we can monitor and evovlve the algorithm until it reaches 0 or max number of generation is reached self.fits = [ ind.fitness.values[0] for ind in self.pop ] self.fits # Disable start and enable stop self.btnStart.setEnabled(False) self.btnStop.setEnabled(True) self.gaParams.setEnabled(False) self.tbxNoQueens.setEnabled(False) self.cbxNoVis.setEnabled(False) # Start evolution self.evolve() # Mean number of generations nedeed for finding 5 correct solutions -- Added by Denis Lazor mean_gen = min(generations, key=lambda x: abs(x - statistics.mean( generations))) # Index of mean_gen value -- Added by Denis Lazor mean_idx = generations.index(mean_gen) write_to_file( combination_series[mean_idx], parameter_name, permutation_checked ) # First name will be "original", second one "elites" -- Added by Denis Lazor parameter_name = "elites" print_results(b, p, m, e, trials, generations, mean_gen, NGEN) # Clearing past lists -- Added by Denis Lazor generations = [] combination_series = [] # Reducing number of combinations and changing .csv file for writing -- Added by Denis Lazor ELITE_SIZES = ELITE_SIZES[0:1] parameter_name = "mutation" MUTATION_SIZES = MUTATION_SIZES[0:1] parameter_name = "population" POPULATION_SIZES = POPULATION_SIZES[0:1] parameter_name = "original" n = 30000 # Increasing generation size for 24x24 board def btnStop_Click(self): global stop_evolution stop_evolution = True #Disable stop and enable start self.btnStop.setEnabled(False) self.btnStart.setEnabled(True) self.gaParams.setEnabled(True) self.tbxNoQueens.setEnabled(True) self.cbxNoVis.setEnabled(True) #Function for GA evolution def evolve(self): global q_min_series global q_max_series global q_avg_series global success global generations global combination_series global NO_QUEENS global NGEN global POP_SIZE global MUTPB global NELT combination_current_series = [] # Variable for keeping track of the number of generations curr_g = 0 # Begin the evolution till goal is reached or max number of generation is reached while min(self.fits) != 0 and curr_g < NGEN: #Check if evolution and thread need to stop if stop_evolution: break #Break the evolution loop # A new generation curr_g = curr_g + 1 #print("-- Generation %i --" % curr_g) # Select the next generation individuals #Select POP_SIZE - NELT number of individuals. Since recombination is between neigbours, not two naighbours should be the clone of the same individual offspring = [] offspring.append(self.toolbox.select( self.pop, 1)[0]) #add first selected individual for i in range( POP_SIZE - NELT - 1 ): # -1 because the first seleceted individual is already added while True: new_o = self.toolbox.select(self.pop, 1)[0] if new_o != offspring[len( offspring ) - 1]: #if it is different than the last inserted then add to offspring and break offspring.append(new_o) break # Clone the selected individuals because all of the changes are inplace offspring = list(map(self.toolbox.clone, offspring)) # Apply crossover on the selected offspring for child1, child2 in zip(offspring[::2], offspring[1::2]): self.toolbox.mate(child1, child2) #inplace recombination #Invalidate new children fitness values del child1.fitness.values del child2.fitness.values #Apply mutation on the offspring for mutant in offspring: if random.random() < MUTPB: self.toolbox.mutate(mutant) del mutant.fitness.values #Add elite individuals #Is clonning needed? offspring.extend( list(map(self.toolbox.clone, tools.selBest(self.pop, NELT)))) # Evaluate the individuals with an invalid fitness invalid_ind = [ind for ind in offspring if not ind.fitness.valid] fitnesses = map(self.toolbox.evaluate, invalid_ind) for ind, fit in zip(invalid_ind, fitnesses): ind.fitness.values = fit #print(" Evaluated %i individuals" % len(invalid_ind)) #Replace population with offspring self.pop[:] = offspring # Gather all the fitnesses in one list and print the stats self.fits = [ind.fitness.values[0] for ind in self.pop] length = len(self.pop) mean = sum(self.fits) / length sum2 = sum(x * x for x in self.fits) std = abs(sum2 / length - mean**2)**0.5 q_min_series.append(curr_g, min(self.fits)) q_max_series.append(curr_g, max(self.fits)) q_avg_series.append(curr_g, mean) combination_current_series.append( min(self.fits) ) # Saving min_series fitness values of an experiment -- Added by Denis Lazor # Checking if fitness value of 0 is reached -- Added by Denis Lazor for f in self.fits: if f == 0: success = success + 1 generations.append(curr_g) combination_series.append(combination_current_series) break #print(" Min %s" % q_min_series.at(q_min_series.count()-1).y()) #print(" Max %s" % q_max_series.at(q_max_series.count()-1).y()) #print(" Avg %s" % mean) #print(" Std %s" % std) if self.cbxNoVis.isChecked(): app.processEvents() else: #Draw queen positions of best individual on a image best_ind = tools.selBest(self.pop, 1)[0] self.updateWorldFrame(generateQueenImage(best_ind)) self.chart = QChart() #self.chart.addSeries(q_min_series) #self.chart.addSeries(q_max_series) #q_avg_series.setName("Board: " + str(b) + " Population: " + str(p) + " Elite: " + str(e) + " Mutation:" + str(m*100) + "% " + "Generations:" + str(NGSEN)) self.chart.addSeries(q_avg_series) self.chart.setTitle("QN: " + str(NO_QUEENS) + " POP: " + str(POP_SIZE) + " EL: " + str(NELT) + " MT: " + str(MUTPB * 100) + "% ") self.chart.setAnimationOptions(QChart.NoAnimation) self.chart.createDefaultAxes() self.frameChart.setChart(self.chart) #Printing best individual best_ind = tools.selBest(self.pop, 1)[0] #print("Best individual is %s, %s \n" % (best_ind, best_ind.fitness.values)) #Visulaize final solution if self.cbxNoVis.isChecked(): #Draw queen positions of best individual on a image best_ind = tools.selBest(self.pop, 1)[0] self.updateWorldFrame(generateQueenImage(best_ind)) self.chart = QChart() #self.chart.addSeries(q_min_series) #self.chart.addSeries(q_max_series) self.chart.addSeries(q_avg_series) self.chart.setTitle("QN: " + str(NO_QUEENS) + " POP: " + str(POP_SIZE) + " EL: " + str(NELT) + " MT: " + str(MUTPB * 100) + "% ") self.chart.setAnimationOptions(QChart.NoAnimation) self.chart.createDefaultAxes() self.frameChart.setChart(self.chart) #Disable stop and enable start self.btnStop.setEnabled(False) self.btnStart.setEnabled(True) self.gaParams.setEnabled(True) self.tbxNoQueens.setEnabled(True) self.cbxNoVis.setEnabled(True) def updateWorldFrame(self, queens_img): #new_image = QPixmap(1000,1000) self.new_image.fill() #White color is default painter = QPainter(self.new_image) #First draw the table painter.drawPixmap(self.new_image.rect(), self.img) #Then draw the queens painter.drawImage(self.new_image.rect(), queens_img) painter.end() #Set new image to the frame self.frameWorld.img = self.new_image #Redrawing frames self.frameWorld.repaint() self.frameChart.repaint() app.processEvents() def btnSaveWorld_Click(self): filename, _ = QFileDialog.getSaveFileName(None, "Save world as a image", "", "Image Files (*.png)") self.frameWorld.img.save(filename, "PNG") print("World image saved to: ", filename) def btnSaveChart_CLick(self): p = self.frameChart.grab() filename, _ = QFileDialog.getSaveFileName( None, "Save series chart as a image", "", "Image Files (*.png)") p.save(filename, "PNG") print("Chart series image saved to: ", filename) def btnSaveChartSeries_Click(self): global q_min_series global q_max_series global q_avg_series filename, _ = QFileDialog.getSaveFileName(None, "Save series to text file", "", "Text Files (*.txt, *.csv)") with open(filename, 'w') as dat: for i in range(q_min_series.count()): dat.write('%f,%f,%f\n' % (q_min_series.at(i).y(), q_avg_series.at(i).y(), q_max_series.at(i).y())) print("Chart series saved to: ", filename)
class Ui_MainWindow(QtWidgets.QMainWindow): def setupUi(self): self.setObjectName("MainWindow") self.resize(850, 550) self.setWindowTitle("Rastrigin") self.centralwidget = QtWidgets.QWidget(self) self.centralwidget.setObjectName("centralwidget") self.frameChart = QChartView(self.centralwidget) self.frameChart.setGeometry(QtCore.QRect(10, 10, 620, 500)) self.frameChart.setFrameShape(QtWidgets.QFrame.Box) self.frameChart.setFrameShadow(QtWidgets.QFrame.Sunken) self.frameChart.setRenderHint(QPainter.Antialiasing) self.frameChart.setObjectName("frameChart") self.genParams = QtWidgets.QGroupBox(self.centralwidget) self.genParams.setGeometry(QtCore.QRect(650, 10, 161, 110)) self.genParams.setObjectName("genParams") self.genParams.setTitle("General parameters") self.label1 = QtWidgets.QLabel(self.genParams) self.label1.setGeometry(QtCore.QRect(10, 20, 61, 16)) self.label1.setObjectName("label1") self.label1.setText("Population:") self.label2 = QtWidgets.QLabel(self.genParams) self.label2.setGeometry(QtCore.QRect(10, 50, 91, 16)) self.label2.setObjectName("label2") self.label2.setText("No. generations:") self.label3 = QtWidgets.QLabel(self.genParams) self.label3.setGeometry(QtCore.QRect(10, 80, 81, 16)) self.label3.setObjectName("label3") self.label3.setText("No. dimensions:") self.tbxPopulation = QtWidgets.QLineEdit(self.genParams) self.tbxPopulation.setGeometry(QtCore.QRect(100, 20, 51, 20)) self.tbxPopulation.setObjectName("tbxPopulation") self.tbxGenerations = QtWidgets.QLineEdit(self.genParams) self.tbxGenerations.setGeometry(QtCore.QRect(100, 50, 51, 20)) self.tbxGenerations.setObjectName("tbxGenerations") self.tbxDimensions = QtWidgets.QLineEdit(self.genParams) self.tbxDimensions.setGeometry(QtCore.QRect(100, 80, 51, 20)) self.tbxDimensions.setObjectName("tbxDimensions") self.gaParams = QtWidgets.QGroupBox(self.centralwidget) self.gaParams.setGeometry(QtCore.QRect(650, 130, 191, 105)) self.gaParams.setObjectName("gaParams") self.gaParams.setTitle("GA parameters") self.label4 = QtWidgets.QLabel(self.gaParams) self.label4.setGeometry(QtCore.QRect(10, 20, 61, 16)) self.label4.setObjectName("label4") self.label4.setText("Mutation:") self.label5 = QtWidgets.QLabel(self.gaParams) self.label5.setGeometry(QtCore.QRect(10, 50, 91, 16)) self.label5.setObjectName("label5") self.label5.setText("Elite members:") self.label9 = QtWidgets.QLabel(self.gaParams) self.label9.setGeometry(QtCore.QRect(10, 80, 61, 16)) self.label9.setObjectName("label9") self.label9.setText("Max abs.:") self.tbxMutation = QtWidgets.QLineEdit(self.gaParams) self.tbxMutation.setGeometry(QtCore.QRect(100, 20, 51, 20)) self.tbxMutation.setObjectName("tbxMutation") self.tbxElite = QtWidgets.QLineEdit(self.gaParams) self.tbxElite.setGeometry(QtCore.QRect(100, 50, 51, 20)) self.tbxElite.setObjectName("tbxElite") self.tbxMaxAbs = QtWidgets.QLineEdit(self.gaParams) self.tbxMaxAbs.setGeometry(QtCore.QRect(100, 80, 51, 20)) self.tbxMaxAbs.setObjectName("tbxMAxAbs") self.psoParams = QtWidgets.QGroupBox(self.centralwidget) self.psoParams.setGeometry(QtCore.QRect(650, 240, 161, 110)) self.psoParams.setObjectName("psoParams") self.psoParams.setTitle("PSO parameters") self.label6 = QtWidgets.QLabel(self.psoParams) self.label6.setGeometry(QtCore.QRect(10, 20, 61, 16)) self.label6.setObjectName("label6") self.label6.setText("Inertia factor:") self.label7 = QtWidgets.QLabel(self.psoParams) self.label7.setGeometry(QtCore.QRect(10, 50, 91, 16)) self.label7.setObjectName("label7") self.label7.setText("Personal factor:") self.label8 = QtWidgets.QLabel(self.psoParams) self.label8.setGeometry(QtCore.QRect(10, 80, 81, 16)) self.label8.setObjectName("label8") self.label8.setText("Social factor:") self.tbxInertia = QtWidgets.QLineEdit(self.psoParams) self.tbxInertia.setGeometry(QtCore.QRect(100, 20, 51, 20)) self.tbxInertia.setObjectName("tbxInertia") self.tbxPersonal = QtWidgets.QLineEdit(self.psoParams) self.tbxPersonal.setGeometry(QtCore.QRect(100, 50, 51, 20)) self.tbxPersonal.setObjectName("tbxPersonal") self.tbxSocial = QtWidgets.QLineEdit(self.psoParams) self.tbxSocial.setGeometry(QtCore.QRect(100, 80, 51, 20)) self.tbxSocial.setObjectName("tbxSocial") self.cbxNoVis = QtWidgets.QCheckBox(self.centralwidget) self.cbxNoVis.setGeometry(QtCore.QRect(650, 350, 170, 17)) self.cbxNoVis.setObjectName("cbxNoVis") self.cbxNoVis.setText("No visualization per generation") self.btnStartGA = QtWidgets.QPushButton(self.centralwidget) self.btnStartGA.setGeometry(QtCore.QRect(650, 370, 75, 23)) self.btnStartGA.setObjectName("btnStartGA") self.btnStartGA.setText("Start GA") self.btnStartPSO = QtWidgets.QPushButton(self.centralwidget) self.btnStartPSO.setGeometry(QtCore.QRect(650, 400, 75, 23)) self.btnStartPSO.setObjectName("btnStartPSO") self.btnStartPSO.setText("Start PSO") self.btnStop = QtWidgets.QPushButton(self.centralwidget) self.btnStop.setEnabled(False) self.btnStop.setGeometry(QtCore.QRect(740, 370, 75, 53)) self.btnStop.setObjectName("btnStop") self.btnStop.setText("Stop") self.btnSaveChart = QtWidgets.QPushButton(self.centralwidget) self.btnSaveChart.setGeometry(QtCore.QRect(650, 450, 121, 41)) self.btnSaveChart.setObjectName("btnSaveChart") self.btnSaveChart.setText("Save chart as image") self.btnSaveChartSeries = QtWidgets.QPushButton(self.centralwidget) self.btnSaveChartSeries.setGeometry(QtCore.QRect(650, 500, 121, 41)) self.btnSaveChartSeries.setObjectName("btnSaveChartSeries") self.btnSaveChartSeries.setText("Save chart as series") self.setCentralWidget(self.centralwidget) QtCore.QMetaObject.connectSlotsByName(self) #Connect events self.btnStartGA.clicked.connect(self.btnStartGA_Click) self.btnStartPSO.clicked.connect(self.btnStartPSO_Click) self.btnStop.clicked.connect(self.btnStop_Click) self.btnSaveChart.clicked.connect(self.btnSaveChart_CLick) self.btnSaveChartSeries.clicked.connect(self.btnSaveChartSeries_Click) #Set default variables self.tbxGenerations.insert(str(NGEN)) self.tbxPopulation.insert(str(POP_SIZE)) self.tbxDimensions.insert(str(NO_DIMS)) self.tbxMutation.insert(str(GA_MUTPB)) self.tbxElite.insert(str(GA_NELT)) self.tbxMaxAbs.insert(str(GA_MAX_ABS)) self.tbxInertia.insert(str(PSO_INERTIA)) self.tbxPersonal.insert(str(PSO_PERSONAL)) self.tbxSocial.insert(str(PSO_SOCIAL)) def btnStartGA_Click(self): global combination_series # List of lists containing min_series of 5 results -- Added by Denis Lazor global parameter_name # Name of parameter used for writing its data to .csv file -- Added by Denis Lazor global best_fit_values # List containing best fitness values for every of 5 experiments per combination -- Added by Denis Lazor global DIM_SIZES global ELITE_SIZES global MAX_ABS_SIZES global MUTATION_SIZES # Checking if files are empty or not -- Added by Denis Lazor csv_contains_ga = os.stat("graphs_csv/original_ga.csv").st_size != 0 # Clearing non empty files if we are trying to write to them -- Added by Denis Lazor if csv_contains_ga: clear_all_csv("ga") parameter_name = "original" n = 5000 print("GA:\n") # Automation for all necessary combinations -- Added by Denis Lazor for d in DIM_SIZES: MUTATION_SIZES = [0.05, 0.1, 0.2] ELITE_SIZES = [4, 8, 16] MAX_ABS_SIZES = [0.4] for m in MUTATION_SIZES: for e in ELITE_SIZES: for ma in MAX_ABS_SIZES: for i in range(5): # Set global variables global stop_evolution global q_min_series global q_max_series global q_avg_series stop_evolution = False q_min_series.clear() q_max_series.clear() q_avg_series.clear() # Set global variables from information on UI global NGEN global POP_SIZE global GA_MUTPB global GA_NELT global GA_MAX_ABS NGEN = int(self.tbxGenerations.text()) POP_SIZE = int(self.tbxPopulation.text()) GA_MUTPB = m GA_NELT = e GA_MAX_ABS = ma ####Initialize deap GA objects#### # Make creator that minimize. If it would be 1.0 instead od -1.0 than it would be maxmize self.creator = creator self.creator.create("FitnessMin", base.Fitness, weights=(-1.0, )) # Create an individual (a blueprint for cromosomes) as a list with a specified fitness type self.creator.create( "Individual", list, fitness=self.creator.FitnessMin) # Create base toolbox for finishing creation of a individual (cromosome) self.toolbox = base.Toolbox() # Define what type of data (number, gene) will it be in the cromosome self.toolbox.register("attr_float", random.uniform, F_MIN, F_MAX) # Initialization procedure (initRepeat) for the cromosome. For the individual to be completed we need to run initRepeat for the amaout of genes the cromosome includes self.toolbox.register("individual", tools.initRepeat, self.creator.Individual, self.toolbox.attr_float, n=NO_DIMS) # Create a population of individuals (cromosomes). The population is then created by toolbox.population(n=300) where 'n' is the number of cromosomes in population self.toolbox.register("population", tools.initRepeat, list, self.toolbox.individual) # Register evaluation function self.toolbox.register("evaluate", evaluateInd) # Register what genetic operators to use # Standard coding self.toolbox.register( "mate", tools.cxTwoPoint ) # Use two point recombination self.toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=GA_MAX_ABS, indpb=0.5) self.toolbox.register( "select", tools.selTournament, tournsize=3) # Use tournament selection ################################## # Generate initial poplation. Will be a member variable so we can easely pass everything to new thread self.pop = self.toolbox.population(n=POP_SIZE) # Evaluate initial population, we map() the evaluation function to every individual and then assign their respective fitness, map runs evaluate function for each individual in pop fitnesses = list( map(self.toolbox.evaluate, self.pop)) for ind, fit in zip(self.pop, fitnesses): ind.fitness.values = fit # Assign calcualted fitness value to individuals # Extracting all the fitnesses of all individuals in a population so we can monitor and evovlve the algorithm until it reaches 0 or max number of generation is reached self.fits = [ ind.fitness.values[0] for ind in self.pop ] # Disable start and enable stop self.btnStartGA.setEnabled(False) self.btnStartPSO.setEnabled(False) self.btnStop.setEnabled(False) self.genParams.setEnabled(False) self.gaParams.setEnabled(False) self.psoParams.setEnabled(False) self.cbxNoVis.setEnabled(False) # Start evolution self.evolveGA() # Best fitness value -- Added by Denis Lazor best_fit = np.array(min(best_fit_values))[0] mean_fit = np.array( min(best_fit_values, key=lambda x: abs(x - statistics.mean( np.asarray(best_fit_values).flatten()))) )[0] # Index of best fitness value -- Added by Denis Lazor mean_fit_idx = best_fit_values.index(mean_fit) write_to_file(combination_series[mean_fit_idx], parameter_name, "ga") # First name will be "original", second one "max_abs" -- Added by Denis Lazor parameter_name = "max_abs" print_results_GA(POP_SIZE, m, e, ma, mean_fit, best_fit, NGEN, d) # Clearing past lists -- Added by Denis Lazor combination_series = [] best_fit_values = [] # Reducing number of combinations and changing .csv file for writing -- Added by Denis Lazor MAX_ABS_SIZES = MAX_ABS_SIZES[0:1] parameter_name = "elites" ELITE_SIZES = ELITE_SIZES[0:1] parameter_name = "mutation" MUTATION_SIZES = MUTATION_SIZES[0:1] parameter_name = "original" def btnStartPSO_Click(self): global combination_series # List of lists containing min_series of 5 results -- Added by Denis Lazor global parameter_name # Name of parameter used for writing its data to .csv file -- Added by Denis Lazor global best_fit_values # List containing best fitness values for every of 5 experiments per combination -- Added by Denis Lazor global DIM_SIZES global INERTIA_SIZES global PERSONAL_F_SIZES global SOCIAL_F_SIZES # Checking if files are empty or not -- Added by Denis Lazor csv_contains_pso = os.stat("graphs_csv/original_pso.csv").st_size != 0 # Clearing non empty files if we are trying to write to them -- Added by Denis Lazor if csv_contains_pso: clear_all_csv("pso") n = 5000 parameter_name = "original" print("PSO:\n") # Automation for all necessary combinations -- Added by Denis Lazor for d in DIM_SIZES: INERTIA_SIZES = [0.0, 0.37, 0.74] PERSONAL_F_SIZES = [0.5, 1.0, 1.5] SOCIAL_F_SIZES = [0.5, 1.0, 1.5] for in_f in INERTIA_SIZES: for pers_f in PERSONAL_F_SIZES: for soc_f in SOCIAL_F_SIZES: for i in range(5): # Set global variables global stop_evolution global q_min_series global q_max_series global q_avg_series stop_evolution = False q_min_series.clear() q_max_series.clear() q_avg_series.clear() # Set global variables from information on UI global NGEN global POP_SIZE global PSO_INERTIA global PSO_PERSONAL global PSO_SOCIAL NGEN = int(self.tbxGenerations.text()) POP_SIZE = int(self.tbxPopulation.text()) PSO_INERTIA = in_f PSO_PERSONAL = pers_f PSO_SOCIAL = soc_f ####Initialize deap PSO objects#### # Make creator that minimize. If it would be 1.0 instead od -1.0 than it would be maxmize self.creator = creator self.creator.create("FitnessMin", base.Fitness, weights=(-1.0, )) # Create an individual (a blueprint for cromosomes) as a list with a specified fitness type self.creator.create( "Particle", list, fitness=self.creator.FitnessMin, speed=list, best=None) # Create base toolbox for finishing creation of a individual (particle) and population self.toolbox = base.Toolbox() # Particle initialization self.toolbox.register("particle", generateParticle, cr=self.creator, size=NO_DIMS, min_val=F_MIN, max_val=F_MAX) # Create a population of individuals (particles). The population is then created by e.g. toolbox.population(n=300) where 'n' is the number of particles in population self.toolbox.register("population", tools.initRepeat, list, self.toolbox.particle) # Update function for each particle self.toolbox.register("update", updateParticle) # Evaluation function for each particle self.toolbox.register("evaluate", evaluateInd) ################################## # Create population self.pop = self.toolbox.population(n=POP_SIZE) # Evaluate initial population, we map() the evaluation function to every individual and then assign their respective fitness, map runs emaluet function for each individual in pop fitnesses = list( map(self.toolbox.evaluate, self.pop)) for ind, fit in zip(self.pop, fitnesses): ind.fitness.values = fit # Extracting all the fitnesses of all individuals in a population so we can monitor and evovlve the algorithm until it reaches 0 or max number of generation is reached self.fits = [ ind.fitness.values[0] for ind in self.pop ] # Extraction current best position self.global_best_position = tools.selBest( self.pop, 1)[0][:] # Disable start and enable stop self.btnStartGA.setEnabled(False) self.btnStartPSO.setEnabled(False) self.btnStop.setEnabled(False) self.genParams.setEnabled(False) self.gaParams.setEnabled(False) self.psoParams.setEnabled(False) self.cbxNoVis.setEnabled(False) # Start evolution self.evolvePSO() # Best fitness value -- Added by Denis Lazor best_fit = np.array(min(best_fit_values))[0] mean_fit = np.array( min(best_fit_values, key=lambda x: abs(x - statistics.mean( np.asarray(best_fit_values).flatten()))) )[0] # Index of best fitness value -- Added by Denis Lazor mean_fit_idx = best_fit_values.index(mean_fit) write_to_file(combination_series[mean_fit_idx], parameter_name, "pso") # First name will be "original", second one "social_factor" -- Added by Denis Lazor parameter_name = "social_factor" print_results_PSO(POP_SIZE, in_f, pers_f, soc_f, mean_fit, best_fit, NGEN, d) # Clearing past lists -- Added by Denis Lazor print(best_fit_values) combination_series = [] best_fit_values = [] # Reducing number of combinations and changing .csv file for writing -- Added by Denis Lazor SOCIAL_F_SIZES = SOCIAL_F_SIZES[0:1] parameter_name = "personal_factor" PERSONAL_F_SIZES = PERSONAL_F_SIZES[0:1] parameter_name = "inertia" INERTIA_SIZES = INERTIA_SIZES[0:1] parameter_name = "original" def btnStop_Click(self): global stop_evolution stop_evolution = True #Disable stop and enable start self.btnStartGA.setEnabled(True) self.btnStartPSO.setEnabled(True) self.btnStop.setEnabled(False) self.genParams.setEnabled(True) self.gaParams.setEnabled(True) self.psoParams.setEnabled(True) self.cbxNoVis.setEnabled(True) #Function for GA evolution def evolveGA(self): global q_min_series global q_max_series global q_avg_series global combination_series global best_fit_values combination_current_series = [ ] # Clearing fitness values series -- Added by Denis Lazor # Variable for keeping track of the number of generations curr_g = 0 # Begin the evolution till goal is reached or max number of generation is reached while min(self.fits) != 0 and curr_g < NGEN: #Check if evolution and thread need to stop if stop_evolution: break #Break the evolution loop # A new generation curr_g = curr_g + 1 # print("-- Generation %i --" % curr_g) # Select the next generation individuals #Select POP_SIZE - NELT number of individuals. Since recombination is between neigbours, not two naighbours should be the clone of the same individual offspring = [] offspring.append(self.toolbox.select( self.pop, 1)[0]) #add first selected individual for i in range( POP_SIZE - GA_NELT - 1 ): # -1 because the first seleceted individual is already added while True: new_o = self.toolbox.select(self.pop, 1)[0] if new_o != offspring[len( offspring ) - 1]: #if it is different than the last inserted then add to offspring and break offspring.append(new_o) break # Clone the selected individuals because all of the changes are inplace offspring = list(map(self.toolbox.clone, offspring)) # Apply crossover on the selected offspring for child1, child2 in zip(offspring[::2], offspring[1::2]): self.toolbox.mate(child1, child2) #inplace recombination #Invalidate new children fitness values del child1.fitness.values del child2.fitness.values #Apply mutation on the offspring for mutant in offspring: if random.random() < GA_MUTPB: self.toolbox.mutate(mutant) del mutant.fitness.values #Add elite individuals #Is clonning needed? offspring.extend( list(map(self.toolbox.clone, tools.selBest(self.pop, GA_NELT)))) # Evaluate the individuals with an invalid fitness invalid_ind = [ind for ind in offspring if not ind.fitness.valid] fitnesses = map(self.toolbox.evaluate, invalid_ind) for ind, fit in zip(invalid_ind, fitnesses): ind.fitness.values = fit # print(" Evaluated %i individuals" % len(invalid_ind)) #Replace population with offspring self.pop[:] = offspring # Gather all the fitnesses in one list and print the stats self.fits = [ind.fitness.values[0] for ind in self.pop] length = len(self.pop) mean = sum(self.fits) / length sum2 = sum(x * x for x in self.fits) std = abs(sum2 / length - mean**2)**0.5 q_min_series.append(curr_g, min(self.fits)) q_max_series.append(curr_g, max(self.fits)) q_avg_series.append(curr_g, mean) combination_current_series.append( min(self.fits) ) # Saving min_series fitness values of an experiment -- Added by Denis Lazor # print(" Min %s" % q_min_series.at(q_min_series.count()-1).y()) # print(" Max %s" % q_max_series.at(q_max_series.count()-1).y()) # print(" Avg %s" % mean) # print(" Std %s" % std) # if self.cbxNoVis.isChecked(): app.processEvents() else: self.chart = QChart() self.chart.addSeries(q_min_series) self.chart.addSeries(q_max_series) self.chart.addSeries(q_avg_series) self.chart.setTitle("Fitness value over time") self.chart.setAnimationOptions(QChart.NoAnimation) self.chart.createDefaultAxes() self.frameChart.setChart(self.chart) self.frameChart.repaint() app.processEvents() #Printing best individual best_ind = tools.selBest(self.pop, 1)[0] # print("Best individual is %s, %s" % (best_ind, best_ind.fitness.values)) #Visulaize final solution if self.cbxNoVis.isChecked(): self.chart = QChart() self.chart.addSeries(q_min_series) self.chart.addSeries(q_max_series) self.chart.addSeries(q_avg_series) self.chart.setTitle("Fitness value over time") self.chart.setAnimationOptions(QChart.NoAnimation) self.chart.createDefaultAxes() self.frameChart.setChart(self.chart) self.frameChart.repaint() #Disable stop and enable start self.btnStartGA.setEnabled(True) self.btnStartPSO.setEnabled(True) self.btnStop.setEnabled(False) self.genParams.setEnabled(True) self.gaParams.setEnabled(True) self.psoParams.setEnabled(True) self.cbxNoVis.setEnabled(True) app.processEvents() combination_series.append(combination_current_series ) # Saving 5 results -- Added by Denis Lazor best_fit_values.append( best_ind.fitness.values ) # Adding best fitness value of experiment -- Added by Denis Lazor #Function for GA evolution def evolvePSO(self): global q_min_series global q_max_series global q_avg_series global combination_series global best_fit_values combination_current_series = [ ] # Clearing fitness values series -- Added by Denis Lazor # Variable for keeping track of the number of generations curr_g = 0 while min(self.fits) != 0.0 and curr_g < NGEN: #Check if evolution and thread need to stop if stop_evolution: break #Break the evolution loop # A new generation curr_g = curr_g + 1 # print("-- Generation %i --" % curr_g) #Update particle position and evaluate particle for particle in self.pop: #Update self.toolbox.update(particle, self.global_best_position, PSO_INERTIA, PSO_PERSONAL, PSO_SOCIAL) #Evaluate fit = self.toolbox.evaluate(particle) #Update best position if fit[0] < particle.fitness.values[0]: particle.best = particle[:] #Update fitness particle.fitness.values = fit #Extracting all the fitnesses of all individuals in a population so we can monitor and evovlve the algorithm until it reaches 0 or max number of generation is reached self.fits = [ind.fitness.values[0] for ind in self.pop] #Extraction current best position self.global_best_position = tools.selBest(self.pop, 1)[0][:] #Stats length = len(self.pop) mean = sum(self.fits) / length sum2 = sum(x * x for x in self.fits) std = abs(sum2 / length - mean**2)**0.5 q_min_series.append(curr_g, min(self.fits)) q_max_series.append(curr_g, max(self.fits)) q_avg_series.append(curr_g, mean) combination_current_series.append( min(self.fits) ) # Saving min_series fitness values of an experiment -- Added by Denis Lazor # print(" Min %s" % q_min_series.at(q_min_series.count()-1).y()) # print(" Max %s" % q_max_series.at(q_max_series.count()-1).y()) # print(" Avg %s" % mean) # print(" Std %s" % std) # if self.cbxNoVis.isChecked(): app.processEvents() else: self.chart = QChart() self.chart.addSeries(q_min_series) self.chart.addSeries(q_max_series) self.chart.addSeries(q_avg_series) self.chart.setTitle("Fitness value over time") self.chart.setAnimationOptions(QChart.NoAnimation) self.chart.createDefaultAxes() self.frameChart.setChart(self.chart) self.frameChart.repaint() app.processEvents() #Printing best individual best_ind = tools.selBest(self.pop, 1)[0] # print("Best individual is %s, %s" % (best_ind, best_ind.fitness.values)) #Visulaize final solution if self.cbxNoVis.isChecked(): self.chart = QChart() self.chart.addSeries(q_min_series) self.chart.addSeries(q_max_series) self.chart.addSeries(q_avg_series) self.chart.setTitle("Fitness value over time") self.chart.setAnimationOptions(QChart.NoAnimation) self.chart.createDefaultAxes() self.frameChart.setChart(self.chart) self.frameChart.repaint() #Disable stop and enable start self.btnStartGA.setEnabled(True) self.btnStartPSO.setEnabled(True) self.btnStop.setEnabled(False) self.genParams.setEnabled(True) self.gaParams.setEnabled(True) self.psoParams.setEnabled(True) self.cbxNoVis.setEnabled(True) app.processEvents() combination_series.append(combination_current_series ) # Saving 5 results -- Added by Denis Lazor best_fit_values.append( best_ind.fitness.values ) # Adding best fitness value of experiment -- Added by Denis Lazor def btnSaveChart_CLick(self): p = self.frameChart.grab() filename, _ = QFileDialog.getSaveFileName( None, "Save series chart as a image", "", "Image Files (*.png)") p.save(filename, "PNG") print("Chart series image saved to: ", filename) def btnSaveChartSeries_Click(self): global q_min_series global q_max_series global q_avg_series filename, _ = QFileDialog.getSaveFileName(None, "Save series to text file", "", "Text Files (*.txt, *.csv)") with open(filename, 'w') as dat: for i in range(q_min_series.count()): dat.write('%f,%f,%f\n' % (q_min_series.at(i).y(), q_avg_series.at(i).y(), q_max_series.at(i).y())) print("Chart series saved to: ", filename)
class Ui_MainWindow(QtWidgets.QMainWindow): def setupUi(self): self.setObjectName("MainWindow") self.resize(850, 1080) self.setWindowTitle("GA - Queens") self.centralwidget = QtWidgets.QWidget(self) self.centralwidget.setObjectName("centralwidget") self.frameWorld = MyQFrame(self.centralwidget) self.frameWorld.img = QPixmap(1000, 1000) self.frameWorld.setGeometry(QtCore.QRect(10, 10, 620, 600)) self.frameWorld.setFrameShape(QtWidgets.QFrame.Box) self.frameWorld.setFrameShadow(QtWidgets.QFrame.Sunken) self.frameWorld.setObjectName("frameWorld") self.frameChart = QChartView(self.centralwidget) self.frameChart.setGeometry(QtCore.QRect(10, 620, 620, 400)) self.frameChart.setFrameShape(QtWidgets.QFrame.Box) self.frameChart.setFrameShadow(QtWidgets.QFrame.Sunken) self.frameChart.setRenderHint(QPainter.Antialiasing) self.frameChart.setObjectName("frameChart") self.gaParams = QtWidgets.QGroupBox(self.centralwidget) self.gaParams.setGeometry(QtCore.QRect(650, 10, 161, 145)) self.gaParams.setObjectName("gaParams") self.gaParams.setTitle("GA parameters") self.label1 = QtWidgets.QLabel(self.gaParams) self.label1.setGeometry(QtCore.QRect(10, 20, 61, 16)) self.label1.setObjectName("label1") self.label1.setText("Population:") self.label2 = QtWidgets.QLabel(self.gaParams) self.label2.setGeometry(QtCore.QRect(10, 50, 47, 16)) self.label2.setObjectName("label2") self.label2.setText("Mutation:") self.label3 = QtWidgets.QLabel(self.gaParams) self.label3.setGeometry(QtCore.QRect(10, 80, 81, 16)) self.label3.setObjectName("label3") self.label3.setText("Elite members:") self.label4 = QtWidgets.QLabel(self.gaParams) self.label4.setGeometry(QtCore.QRect(10, 110, 91, 16)) self.label4.setObjectName("label4") self.label4.setText("No. generations:") self.tbxPopulation = QtWidgets.QLineEdit(self.gaParams) self.tbxPopulation.setGeometry(QtCore.QRect(100, 20, 51, 20)) self.tbxPopulation.setObjectName("tbxPopulation") self.tbxMutation = QtWidgets.QLineEdit(self.gaParams) self.tbxMutation.setGeometry(QtCore.QRect(100, 50, 51, 20)) self.tbxMutation.setObjectName("tbxMutation") self.tbxElite = QtWidgets.QLineEdit(self.gaParams) self.tbxElite.setGeometry(QtCore.QRect(100, 80, 51, 20)) self.tbxElite.setObjectName("tbxElite") self.tbxGenerations = QtWidgets.QLineEdit(self.gaParams) self.tbxGenerations.setGeometry(QtCore.QRect(100, 110, 51, 20)) self.tbxGenerations.setObjectName("tbxGenerations") self.cbxNoVis = QtWidgets.QCheckBox(self.centralwidget) self.cbxNoVis.setGeometry(QtCore.QRect(650, 170, 170, 17)) self.cbxNoVis.setObjectName("cbxNoVis") self.cbxNoVis.setText("No visualization per generation") self.cbxBorder = QtWidgets.QCheckBox(self.centralwidget) self.cbxBorder.setGeometry(QtCore.QRect(650, 200, 100, 17)) self.cbxBorder.setObjectName("cbxBorder") self.cbxBorder.setText("Border patrol") self.btnStart = QtWidgets.QPushButton(self.centralwidget) self.btnStart.setGeometry(QtCore.QRect(650, 230, 75, 23)) self.btnStart.setObjectName("btnStart") self.btnStart.setText("Start") self.btnStop = QtWidgets.QPushButton(self.centralwidget) self.btnStop.setEnabled(False) self.btnStop.setGeometry(QtCore.QRect(730, 230, 75, 23)) self.btnStop.setObjectName("btnStop") self.btnStop.setText("Stop") self.btnSaveWorld = QtWidgets.QPushButton(self.centralwidget) self.btnSaveWorld.setGeometry(QtCore.QRect(650, 570, 121, 41)) self.btnSaveWorld.setObjectName("btnSaveWorld") self.btnSaveWorld.setText("Save world as image") self.btnSaveChart = QtWidgets.QPushButton(self.centralwidget) self.btnSaveChart.setGeometry(QtCore.QRect(650, 930, 121, 41)) self.btnSaveChart.setObjectName("btnSaveChart") self.btnSaveChart.setText("Save chart as image") self.btnSaveChartSeries = QtWidgets.QPushButton(self.centralwidget) self.btnSaveChartSeries.setGeometry(QtCore.QRect(650, 980, 121, 41)) self.btnSaveChartSeries.setObjectName("btnSaveChartSeries") self.btnSaveChartSeries.setText("Save chart as series") self.setCentralWidget(self.centralwidget) QtCore.QMetaObject.connectSlotsByName(self) #Connect events self.btnStart.clicked.connect(self.btnStart_Click) self.btnStop.clicked.connect(self.btnStop_Click) self.btnSaveWorld.clicked.connect(self.btnSaveWorld_Click) self.btnSaveChart.clicked.connect(self.btnSaveChart_CLick) self.btnSaveChartSeries.clicked.connect(self.btnSaveChartSeries_Click) #Set default GA variables self.tbxGenerations.insert(str(NGEN)) self.tbxPopulation.insert(str(POP_SIZE)) self.tbxMutation.insert(str(MUTPB)) self.tbxElite.insert(str(NELT)) self.new_image = QPixmap(1000, 1000) def btnStart_Click(self): global combination_series # List of lists containing min_series of 5 correct results -- Added by Denis Lazor global parameter_name # Name of parameter used for writing its data to .csv file -- Added by Denis Lazor global best_fit_values # List containing best fitness values for every of 5 experiments per combination -- Added by Denis Lazor global best_individual # Saving best individuals for drawing the best solution -- Added by Denis Lazor global ELITE_SIZES global POPULATION_SIZES global MUTATION_SIZES # Checking if files are empty or not -- Added by Denis Lazor csv_contains = os.stat("graphs_csv/original.csv").st_size != 0 if csv_contains: clear_all_csv() n = 5000 # Automation for all necessary combinations -- Added by Denis Lazor for p in POPULATION_SIZES: for m in MUTATION_SIZES: for e in ELITE_SIZES: for i in range(5): # Set global variables global stop_evolution global q_min_series global q_max_series global q_avg_series stop_evolution = False q_min_series.clear() q_max_series.clear() q_avg_series.clear() # Set global variables from information on UI global NGEN global POP_SIZE global MUTPB global NELT NGEN = n POP_SIZE = p MUTPB = m NELT = e global border_check border_check = self.cbxBorder.isChecked() # Loading Croatia map self.img = QPixmap(620, 600) self.img.load('Croatia620.png') self.frameWorld.img = self.img # Drawing towns painter = QPainter(self.img) painter.setPen(QPen(Qt.black, 10, Qt.SolidLine)) painter.setFont(QFont('Arial', 12)) for i in range(len(gradovi)): x, y = GlobToImgCoords(sirine[i], duzine[i]) painter.drawPoint(x, y) painter.drawText(x + 5, y + 5, gradovi[i]) painter.end() # Redrawing frames self.frameWorld.repaint() app.processEvents() ####Initialize deap GA objects#### # Make creator that minimize. If it would be 1.0 instead od -1.0 than it would be maxmize creator.create("FitnessMin", base.Fitness, weights=(-1.0, )) # Create an individual (a blueprint for cromosomes) as a list with a specified fitness type creator.create("Individual", list, fitness=creator.FitnessMin) # Create base toolbox for finishing creation of a individual (cromosome) self.toolbox = base.Toolbox() # This is if we want a permutation coding of genes in the cromosome self.toolbox.register("indices", random.sample, range(IND_SIZE), IND_SIZE) # initIterate requires that the generator of genes (such as random.sample) generates an iterable (a list) variable self.toolbox.register("individual", tools.initIterate, creator.Individual, self.toolbox.indices) # Create a population of individuals (cromosomes). The population is then created by toolbox.population(n=300) where 'n' is the number of cromosomes in population self.toolbox.register("population", tools.initRepeat, list, self.toolbox.individual) # Register evaluation function self.toolbox.register("evaluate", evaluateInd) # Register what genetic operators to use self.toolbox.register( "mate", tools.cxUniformPartialyMatched, indpb=0.2 ) # Use uniform recombination for permutation coding # Permutation coding self.toolbox.register("mutate", tools.mutShuffleIndexes, indpb=0.2) self.toolbox.register( "select", tools.selTournament, tournsize=3) # Use tournament selection ################################## # Generate initial poplation. Will be a member variable so we can easely pass everything to new thread self.pop = self.toolbox.population(n=POP_SIZE) # Evaluate initial population, we map() the evaluation function to every individual and then assign their respective fitness, map runs evaluate function for each individual in pop fitnesses = list(map(self.toolbox.evaluate, self.pop)) for ind, fit in zip(self.pop, fitnesses): ind.fitness.values = fit # Assign calcualted fitness value to individuals # Extracting all the fitnesses of all individuals in a population so we can monitor and evovlve the algorithm until it reaches 0 or max number of generation is reached self.fits = [ind.fitness.values[0] for ind in self.pop] # Disable start and enable stop self.btnStart.setEnabled(False) self.btnStop.setEnabled(True) self.gaParams.setEnabled(False) self.cbxBorder.setEnabled(False) self.cbxNoVis.setEnabled(False) # Start evolution self.evolve() # Best fitness value -- Added by Denis Lazor best_fit = np.array(min(best_fit_values))[0] mean_fit = min( best_fit_values, key=lambda x: abs(x - statistics.mean( (np.asarray(best_fit_values)).flatten())))[0] # Index of best fitness value -- Added by Denis Lazor best_fit_idx = best_fit_values.index(best_fit) write_to_file(combination_series[best_fit_idx], parameter_name) # First name will be "original", second one "elites" -- Added by Denis Lazor parameter_name = "elites" print_results(p, m, e, best_fit, mean_fit, NGEN) # Clearing past lists -- Added by Denis Lazor combination_series = [] best_fit_values = [] # Reducing number of combinations and changing .csv file for writing -- Added by Denis Lazor ELITE_SIZES = ELITE_SIZES[0:1] parameter_name = "mutation" MUTATION_SIZES = MUTATION_SIZES[0:1] parameter_name = "population" print("Best individual: " + str(best_individual)) self.updateWorldFrame(generateWorldImage( best_individual)) # Drawing best solution -- Added by Denis Lazor def btnStop_Click(self): global stop_evolution stop_evolution = True #Disable stop and enable start self.btnStop.setEnabled(False) self.btnStart.setEnabled(True) self.gaParams.setEnabled(True) self.cbxBorder.setEnabled(True) self.cbxNoVis.setEnabled(True) #Function for GA evolution def evolve(self): global q_min_series global q_max_series global q_avg_series global best_fit_values global combination_series global best_individual combination_current_series = [ ] # Clearing fitness values series -- Added by Denis Lazor # Variable for keeping track of the number of generations curr_g = 0 # Begin the evolution till goal is reached or max number of generation is reached while min(self.fits) != 0 and curr_g < NGEN: #Check if evolution and thread need to stop if stop_evolution: break #Break the evolution loop # A new generation curr_g = curr_g + 1 #print("-- Generation %i --" % curr_g) # Select the next generation individuals #Select POP_SIZE - NELT number of individuals. Since recombination is between neigbours, not two naighbours should be the clone of the same individual offspring = [] offspring.append(self.toolbox.select( self.pop, 1)[0]) #add first selected individual for i in range( POP_SIZE - NELT - 1 ): # -1 because the first seleceted individual is already added while True: new_o = self.toolbox.select(self.pop, 1)[0] if new_o != offspring[len( offspring ) - 1]: #if it is different than the last inserted then add to offspring and break offspring.append(new_o) break # Clone the selected individuals because all of the changes are inplace offspring = list(map(self.toolbox.clone, offspring)) # Apply crossover on the selected offspring for child1, child2 in zip(offspring[::2], offspring[1::2]): self.toolbox.mate(child1, child2) #inplace recombination #Invalidate new children fitness values del child1.fitness.values del child2.fitness.values #Apply mutation on the offspring for mutant in offspring: if random.random() < MUTPB: self.toolbox.mutate(mutant) del mutant.fitness.values #Add elite individuals #Is clonning needed? offspring.extend( list(map(self.toolbox.clone, tools.selBest(self.pop, NELT)))) # Evaluate the individuals with an invalid fitness invalid_ind = [ind for ind in offspring if not ind.fitness.valid] fitnesses = map(self.toolbox.evaluate, invalid_ind) for ind, fit in zip(invalid_ind, fitnesses): ind.fitness.values = fit #print(" Evaluated %i individuals" % len(invalid_ind)) #Replace population with offspring self.pop[:] = offspring # Gather all the fitnesses in one list and print the stats self.fits = [ind.fitness.values[0] for ind in self.pop] length = len(self.pop) mean = sum(self.fits) / length sum2 = sum(x * x for x in self.fits) std = abs(sum2 / length - mean**2)**0.5 q_min_series.append(curr_g, min(self.fits)) q_max_series.append(curr_g, max(self.fits)) q_avg_series.append(curr_g, mean) combination_current_series.append( min(self.fits) ) # Saving min_series fitness values of an experiment -- Added by Denis Lazor #print(" Min %s" % q_min_series.at(q_min_series.count()-1).y()) #print(" Max %s" % q_max_series.at(q_max_series.count()-1).y()) #print(" Avg %s" % mean) #print(" Std %s" % std) if self.cbxNoVis.isChecked(): app.processEvents() else: self.chart = QChart() self.chart.addSeries(q_min_series) self.chart.addSeries(q_max_series) self.chart.addSeries(q_avg_series) self.chart.setTitle("Fitness value over time") self.chart.setAnimationOptions(QChart.NoAnimation) self.chart.createDefaultAxes() self.frameChart.setChart(self.chart) #Draw queen positions of best individual on a image best_ind = tools.selBest(self.pop, 1)[0] self.updateWorldFrame(generateWorldImage(best_ind)) #Printing best individual best_ind = tools.selBest(self.pop, 1)[0] #print("Best individual is %s, %s" % (best_ind, best_ind.fitness.values)) combination_series.append( combination_current_series ) # Saving best 5 results -- Added by Denis Lazor if not best_individual: best_individual = best_ind elif best_ind.fitness.values < best_individual.fitness.values: # Saving best individual in all combinations -- Added by Denis Lazor best_individual = best_ind best_fit_values.append( best_ind.fitness.values ) # Adding best fitness value of experiment -- Added by Denis Lazor # #Visulaize final solution # if self.cbxNoVis.isChecked(): # self.chart = QChart() # self.chart.addSeries(q_min_series) # self.chart.addSeries(q_max_series) # self.chart.addSeries(q_avg_series) # self.chart.setTitle("Fitness value over time") # self.chart.setAnimationOptions(QChart.NoAnimation) # self.chart.createDefaultAxes() # self.frameChart.setChart(self.chart) # # #Draw queen positions of best individual on a image # best_ind = tools.selBest(self.pop, 1)[0] # self.updateWorldFrame(generateWorldImage(best_ind)) #Disable stop and enable start self.btnStop.setEnabled(False) self.btnStart.setEnabled(True) self.gaParams.setEnabled(True) self.cbxBorder.setEnabled(True) self.cbxNoVis.setEnabled(True) def updateWorldFrame(self, best_individual_img): #new_image = QPixmap(1000,1000) self.new_image.fill() #White color is default painter = QPainter(self.new_image) #First draw the map with towns painter.drawPixmap(self.new_image.rect(), self.img) #Then draw the best individual painter.drawImage(self.new_image.rect(), best_individual_img) painter.end() #Set new image to the frame self.frameWorld.img = self.new_image #Redrawing frames self.frameWorld.repaint() self.frameChart.repaint() app.processEvents() def btnSaveWorld_Click(self): filename, _ = QFileDialog.getSaveFileName(None, "Save world as a image", "", "Image Files (*.png)") self.frameWorld.img.save(filename, "PNG") print("World image saved to: ", filename) def btnSaveChart_CLick(self): p = self.frameChart.grab() filename, _ = QFileDialog.getSaveFileName( None, "Save series chart as a image", "", "Image Files (*.png)") p.save(filename, "PNG") print("Chart series image saved to: ", filename) def btnSaveChartSeries_Click(self): global q_min_series global q_max_series global q_avg_series filename, _ = QFileDialog.getSaveFileName(None, "Save series to text file", "", "Text Files (*.txt, *.csv)") with open(filename, 'w') as dat: for i in range(q_min_series.count()): dat.write('%f,%f,%f\n' % (q_min_series.at(i).y(), q_avg_series.at(i).y(), q_max_series.at(i).y())) print("Chart series saved to: ", filename)