Beispiel #1
0
def test_formula_expressions_can_be_parsed():
    formula = parser.expr(
        'base_value * MULTIPLIER + STAMINA // 3 - SPEED // 5 + ENHANCERS'
    ).compile()
    value = eval(formula, {}, {
        'base_value': 3,
        'MULTIPLIER': 1,
        'STAMINA': 3,
        'SPEED': 10,
        'ENHANCERS': 3
    })
    assert value == 5

    # expr = NumExpr('base_value * MULTIPLIER + STAMINA / 3 - SPEED / 5 + ENHANCERS')

    variables = {
        'base_value': 3,
        'MULTIPLIER': 1,
        'STAMINA': 3,
        'SPEED': 10,
        'ENHANCERS': 3,
        'BANANAS': 8
    }

    formula = Formula(
        'base_value * MULTIPLIER + STAMINA // 3 - SPEED // 5 + ENHANCERS')
    assert formula.evaluate(variables) == 5
Beispiel #2
0
class MathReader(QWidget):
    def __init__(self):
        super().__init__()
        self.iterations = 10000
        self.ro = 0.5
        self.alpha = 0.5
        self.fonts = Fonts(3)
        fonts_used = self.fonts.fonts
        self.fonts.load()
        self.network = Network(neurons=(35, 25, len(Constants.symbols)),
                               input_size=21 * 14)
        self.formula = Formula()
        self.file_path = ""
        self.network_ready = False

        self.setWindowTitle("MathReader")
        self.setWindowIcon(QIcon('res/icon.png'))
        grid = QGridLayout()
        self.setFixedSize(730, 500)

        label_math_reader = QLabel("MathReader")
        label_math_reader.setFont(QFont("Ink Free", 20, QFont.Bold))
        label_math_reader.setMaximumHeight(50)
        label_math_reader.setAlignment(Qt.AlignCenter)

        self.btn_save_weights = QPushButton("Save weights")
        self.btn_save_weights.clicked.connect(self.save_weights)
        self.btn_load_weights = QPushButton("Load weights")
        self.btn_load_weights.clicked.connect(self.load_weights)
        self.btn_train = QPushButton("Train")
        self.btn_train.clicked.connect(self.open_training_dialog)
        self.btn_browse = QPushButton("Browse")
        self.btn_browse.clicked.connect(self.open_file)
        self.btn_solve = QPushButton("Solve!")
        self.btn_solve.setEnabled(False)
        self.btn_solve.clicked.connect(self.solve_formula)

        label_file = QLabel("Chosen image directory: ")
        label_open_image = QLabel(
            "Use the 'Browse' button to select graphic file, you would like me to read from :)"
        )
        label_open_image.setAlignment(Qt.AlignCenter)
        self.label_image = QLabel("Your graphic file will load here!")
        self.label_image.setStyleSheet("background-color: white")
        self.label_image.setAlignment(Qt.AlignCenter)
        self.browsed_file = QLineEdit()
        self.browsed_file.setReadOnly(True)
        self.browsed_file.setMaximumWidth(300)
        self.solved_formula = QLineEdit()
        self.solved_formula.setReadOnly(True)
        self.solved_formula.setFont(QFont("Bahnschrift", 12))
        self.solved_formula.setAlignment(Qt.AlignCenter)
        label_solved = QLabel("I think it is...")
        label_solved.setMaximumHeight(20)
        label_solved.setAlignment(Qt.AlignBottom)
        self.loading = QProgressBar()
        label_loading = QLabel("Training state: ")

        self.separator_h = QFrame()
        self.separator_h.setFrameShape(QFrame.HLine)
        self.separator_h.setFrameShadow(QFrame.Sunken)
        separator_v = QFrame()
        separator_v.setFrameShape(QFrame.VLine)
        separator_v.setFrameShadow(QFrame.Sunken)

        start_state = "Loaded " + str(fonts_used) + " fonts"
        start_state += ("\nInitializing network with layers of sizes " +
                        str(self.network.neurons))
        self.label_state = QLabel(start_state)
        self.label_state.setStyleSheet("background-color: white")
        self.label_state.setAlignment(Qt.AlignCenter)

        self.training_dialog = QDialog()
        self.training_params = QLabel(
            "Here you can specify training parameters: ")
        self.choose_iterations_label = QLabel("Iterations number: ")
        self.choose_alpha_label = QLabel("\u03B1 value: ")
        self.choose_rho_label = QLabel("\u03C1 value: ")
        self.choose_iterations_input = QLineEdit()
        self.choose_iterations_input.setText("10000")
        self.choose_alpha_input = QLineEdit()
        self.choose_alpha_input.setText("0.5")
        self.choose_rho_input = QLineEdit()
        self.choose_rho_input.setText("0.5")
        self.btn_apply = QPushButton("Apply")
        self.btn_apply.setMaximumWidth(80)

        grid.addWidget(label_math_reader, 0, 0, 1, 1)
        grid.addWidget(self.btn_train, 1, 0)
        grid.addWidget(self.btn_save_weights, 2, 0)
        grid.addWidget(self.btn_load_weights, 3, 0)
        grid.addWidget(self.btn_solve, 5, 0)
        grid.addWidget(separator_v, 0, 1, 10, 1)

        grid.addWidget(label_open_image, 0, 2, 1, 3)
        grid.addWidget(label_file, 1, 2, 1, 1)
        grid.addWidget(self.browsed_file, 1, 3, 1, 1)
        grid.addWidget(self.btn_browse, 1, 4, 1, 1)
        grid.addWidget(self.label_image, 2, 2, 7, 3)
        grid.addWidget(label_loading, 9, 2, Qt.AlignCenter)
        grid.addWidget(self.loading, 9, 3, 1, 2)

        grid.addWidget(label_solved, 10, 0, 1, 1)
        grid.addWidget(self.solved_formula, 11, 0, 1, 5)
        grid.addWidget(self.label_state, 12, 0, 1, 5)
        grid.setSpacing(10)
        self.setLayout(grid)

        self.training_dialog.setModal(True)
        self.training_dialog.setWindowTitle("Training Dialog")
        self.training_dialog.setWindowIcon(QIcon('res/icon.png'))
        grid = QGridLayout()
        self.btn_apply.clicked.connect(self.get_training_params)
        self.training_dialog.setFixedSize(230, 150)

        grid.addWidget(self.training_params, 0, 0, 1, 2)
        grid.addWidget(self.separator_h, 1, 0, 1, 2)
        grid.addWidget(self.choose_iterations_label, 2, 0)
        grid.addWidget(self.choose_iterations_input, 2, 1)
        grid.addWidget(self.choose_alpha_label, 3, 0)
        grid.addWidget(self.choose_alpha_input, 3, 1)
        grid.addWidget(self.choose_rho_label, 4, 0)
        grid.addWidget(self.choose_rho_input, 4, 1)
        grid.addWidget(self.btn_apply, 5, 0, 1, 2, Qt.AlignCenter)

        self.training_dialog.setLayout(grid)

    def open_file(self) -> None:
        """
        Opens a file dialog used to load image with a mathematical expression
        """
        file_name, _ = QFileDialog.getOpenFileName(self, 'Open file')
        self.browsed_file.setText(file_name)
        self.file_path = file_name
        self.w = min(530, QPixmap(file_name).width())
        self.h = min(270, QPixmap(file_name).height())
        self.label_image.setPixmap(
            QPixmap(file_name).scaled(self.w, self.h, Qt.KeepAspectRatio))
        self.label_state.setText("Loaded formula from file " + file_name)
        self.btn_solve.setEnabled(True)

    def save_weights(self) -> None:
        """
        Opens a file dialog used to save network parameters to a .csv file
        """
        file_name, _ = QFileDialog.getSaveFileName(self,
                                                   'Save file',
                                                   filter="csv(*.csv)")
        if file_name != '':
            file = open(file_name, 'w')
            with open(file_name):
                self.network.save(file_name)
            file.close()
            self.label_state.setText("Saving weights to file " + file_name)

    def load_weights(self) -> None:
        """
        Opens a file dialog used to load network parameters from a .csv file
        """
        file_name, _ = QFileDialog.getOpenFileName(self,
                                                   'Open file',
                                                   filter="csv(*.csv)")
        if file_name != '':
            self.network.load(file_name)
            self.label_state.setText("Loaded weights from file " + file_name)
            self.network_ready = True

    def solve_formula(self) -> None:
        """
        Solves the formula recognized in the image by the neural network
        """
        if self.network_ready:
            self.label_state.setText(
                "Evaluating formula using neural network.")
            self.formula.load(self.file_path)
            self.solved_formula.setText(self.formula.evaluate(self.network))
            self.label_image.setPixmap(
                QPixmap("data/_output.png").scaled(self.w, self.h,
                                                   Qt.KeepAspectRatio))
        else:
            self.label_state.setText(
                "Please train network or load weights first.")

    def open_training_dialog(self) -> None:
        """
        Opens the dialog before training in which the user sets the number of iterations and additional parameters.
        """
        self.training_dialog.exec()

    def get_training_params(self) -> None:
        """
        Retrieves the training parameters from closed dialog and starts training with
        """
        self.iterations = int(self.choose_iterations_input.text())
        self.ro = float(self.choose_rho_input.text())
        self.alpha = float(self.choose_alpha_input.text())
        self.training_dialog.close()
        t = threading.Thread(target=self.network.fit,
                             args=(self.iterations, self.fonts.data,
                                   self.fonts.labels, self.ro, self.alpha,
                                   self.set_progress_bar))
        t.start()
        self.label_state.setText("Training network for " +
                                 str(self.iterations) + " iterations and " +
                                 str(len(self.fonts.data)) + " samples.")
        self.network_ready = True

    def set_progress_bar(self, progress) -> None:
        """
        Updates the training progress bar with data from neural network
        @param progress: Integer in range from 0 to 100 representing training progress in percentage
        """
        self.loading.setValue(round(float(progress)))
        value = self.loading.value()
        if value < 100:
            self.btn_train.setEnabled(False)
            self.btn_load_weights.setEnabled(False)
            self.btn_save_weights.setEnabled(False)
            self.btn_browse.setEnabled(False)
        else:
            self.label_state.setText("Network successfully trained.")
            self.btn_train.setEnabled(True)
            self.btn_load_weights.setEnabled(True)
            self.btn_save_weights.setEnabled(True)
            self.btn_browse.setEnabled(True)