Skip to content

Commit 1b2157b

Browse files
committed
Test expression checks were added
* Complex real indivs tests were added to check that the algorithm works correctly
1 parent 8c5d447 commit 1b2157b

File tree

7 files changed

+144
-57
lines changed

7 files changed

+144
-57
lines changed

MLC/Common/LispTreeExpr/LispTreeExpr.py

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,46 @@ class ExprException(Exception):
99
pass
1010

1111

12-
class OperationNotFoundException(Exception):
12+
class OperationNotFoundException(ExprException):
1313

1414
def __init__(self, operation, expression):
15-
Exception.__init__(self,
16-
"[EXPR_EXCEPTION] An invalid operation was found. "
17-
"Operation: {0} - Expression: {0}"
18-
.format(expression))
15+
ExprException.__init__(self,
16+
"[EXPR_EXCEPTION] An invalid operation was found. "
17+
"Operation: {0} - Expression: {0}"
18+
.format(expression))
1919

2020

21-
class RootNotFoundExprException(Exception):
21+
class RootNotFoundExprException(ExprException):
2222

2323
def __init__(self, expression):
24-
Exception.__init__(self,
25-
"[EXPR_EXCEPTION] Root node was not found. Expression: {0}"
26-
.format(expression))
24+
ExprException.__init__(self,
25+
"[EXPR_EXCEPTION] Root node was not found. Expression: {0}"
26+
.format(expression))
2727

28+
class TrailingTrashExprException(ExprException):
29+
30+
def __init__(self, expression):
31+
ExprException.__init__(self,
32+
"[EXPR_EXCEPTION] The expression must end with a round bracket ')'. "
33+
"Expression: {0}"
34+
.format(expression))
2835

29-
class NotBalancedParanthesisException(Exception):
36+
37+
class NotBalancedParanthesisException(ExprException):
3038

3139
def __init__(self, expression):
32-
Exception.__init__(self,
33-
"[EXPR_EXCEPTION] Parenthesis in expression are not okay. Expression: {0}"
34-
.format(expression))
40+
ExprException.__init__(self,
41+
"[EXPR_EXCEPTION] Parenthesis in expression are not okay. Expression: {0}"
42+
.format(expression))
3543

3644

37-
class OperationArgumentsAmountException(Exception):
45+
class OperationArgumentsAmountException(ExprException):
3846

3947
def __init__(self, expression):
40-
Exception.__init__(self,
41-
"[EXPR_EXCEPTION] The amount of arguments processed by "
42-
"the operations is not correct . Expression: {0}"
43-
.format(expression))
48+
ExprException.__init__(self,
49+
"[EXPR_EXCEPTION] The amount of arguments processed by "
50+
"the operations is not correct . Expression: {0}"
51+
.format(expression))
4452

4553

4654
class LispTreeExpr(object):
@@ -92,9 +100,12 @@ def check_expression(expression):
92100
if counter != 0:
93101
raise NotBalancedParanthesisException(expression)
94102

103+
# Check the expression to finish with a )
104+
if expression[-1] != ')':
105+
raise TrailingTrashExprException(expression)
106+
95107
# Now the expression is correct. Check the amount of arguments to be correct
96108
def check_operands(expr):
97-
print "Init - Expression: {0}".format(expr)
98109
op_string = expr[1:expr.find(' ')]
99110
expr_op = None
100111
try:

MLC/GUI/Autogenerated/autogenerated.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,9 @@ def setupUi(self, ExperimentWindow):
572572
self.verticalLayout_7.addWidget(self.frame_14)
573573
self.db_view = QtWidgets.QTableView(self.left_menu_frame)
574574
self.db_view.setObjectName("db_view")
575+
self.db_view.horizontalHeader().setCascadingSectionResizes(True)
576+
self.db_view.horizontalHeader().setSortIndicatorShown(True)
577+
self.db_view.horizontalHeader().setStretchLastSection(True)
575578
self.verticalLayout_7.addWidget(self.db_view)
576579
self.horizontalLayout_5.addWidget(self.left_menu_frame)
577580
self.right_menu_frame = QtWidgets.QFrame(self.tab)
@@ -659,6 +662,8 @@ def setupUi(self, ExperimentWindow):
659662
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
660663
self.config_table = QtWidgets.QTableView(self.groupBox)
661664
self.config_table.setObjectName("config_table")
665+
self.config_table.horizontalHeader().setCascadingSectionResizes(True)
666+
self.config_table.horizontalHeader().setSortIndicatorShown(True)
662667
self.config_table.horizontalHeader().setStretchLastSection(True)
663668
self.horizontalLayout_3.addWidget(self.config_table)
664669
self.verticalLayout_2.addWidget(self.groupBox)
@@ -700,7 +705,12 @@ def setupUi(self, ExperimentWindow):
700705
self.verticalLayout_9.setObjectName("verticalLayout_9")
701706
self.first_indivs_table = QtWidgets.QTableView(self.groupBox_10)
702707
self.first_indivs_table.setEnabled(False)
708+
self.first_indivs_table.setCornerButtonEnabled(False)
703709
self.first_indivs_table.setObjectName("first_indivs_table")
710+
self.first_indivs_table.horizontalHeader().setCascadingSectionResizes(True)
711+
self.first_indivs_table.horizontalHeader().setHighlightSections(True)
712+
self.first_indivs_table.horizontalHeader().setMinimumSectionSize(26)
713+
self.first_indivs_table.horizontalHeader().setSortIndicatorShown(True)
704714
self.first_indivs_table.horizontalHeader().setStretchLastSection(True)
705715
self.verticalLayout_9.addWidget(self.first_indivs_table)
706716
self.verticalLayout_8.addWidget(self.groupBox_10)
@@ -736,7 +746,7 @@ def setupUi(self, ExperimentWindow):
736746
ExperimentWindow.setCentralWidget(self.centralWidget)
737747

738748
self.retranslateUi(ExperimentWindow)
739-
self.tabWidget.setCurrentIndex(3)
749+
self.tabWidget.setCurrentIndex(1)
740750
self.next_gen_button.clicked.connect(ExperimentWindow.on_next_gen_button_clicked)
741751
self.save_config_button.clicked.connect(ExperimentWindow.on_save_config_button_clicked)
742752
self.dimension_check.clicked.connect(ExperimentWindow.on_dimension_check_clicked)

MLC/GUI/Autogenerated/mlc_qtcreator/experiment.ui

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<enum>QTabWidget::North</enum>
2525
</property>
2626
<property name="currentIndex">
27-
<number>0</number>
27+
<number>1</number>
2828
</property>
2929
<widget class="QWidget" name="experiment_tab">
3030
<property name="layoutDirection">
@@ -390,7 +390,17 @@
390390
</widget>
391391
</item>
392392
<item>
393-
<widget class="QTableView" name="db_view"/>
393+
<widget class="QTableView" name="db_view">
394+
<attribute name="horizontalHeaderCascadingSectionResizes">
395+
<bool>true</bool>
396+
</attribute>
397+
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
398+
<bool>true</bool>
399+
</attribute>
400+
<attribute name="horizontalHeaderStretchLastSection">
401+
<bool>true</bool>
402+
</attribute>
403+
</widget>
394404
</item>
395405
</layout>
396406
</widget>
@@ -575,6 +585,12 @@
575585
</property>
576586
<item>
577587
<widget class="QTableView" name="config_table">
588+
<attribute name="horizontalHeaderCascadingSectionResizes">
589+
<bool>true</bool>
590+
</attribute>
591+
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
592+
<bool>true</bool>
593+
</attribute>
578594
<attribute name="horizontalHeaderStretchLastSection">
579595
<bool>true</bool>
580596
</attribute>
@@ -656,6 +672,18 @@
656672
<property name="cornerButtonEnabled">
657673
<bool>false</bool>
658674
</property>
675+
<attribute name="horizontalHeaderCascadingSectionResizes">
676+
<bool>true</bool>
677+
</attribute>
678+
<attribute name="horizontalHeaderHighlightSections">
679+
<bool>true</bool>
680+
</attribute>
681+
<attribute name="horizontalHeaderMinimumSectionSize">
682+
<number>26</number>
683+
</attribute>
684+
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
685+
<bool>true</bool>
686+
</attribute>
659687
<attribute name="horizontalHeaderStretchLastSection">
660688
<bool>true</bool>
661689
</attribute>

MLC/GUI/Experiment/ExperimentWindow.py

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import time
88

99
from MLC.Log.log import get_gui_logger
10+
from MLC.GUI.util import test_individual_value
1011
from MLC.GUI.Autogenerated.autogenerated import Ui_ExperimentWindow
1112
from MLC.GUI.Experiment.ArduinoConfigManager.BoardConfigurationWindow import BoardConfigurationWindow
1213
from MLC.GUI.Experiment.ChartConfiguration import ChartConfiguration
@@ -32,7 +33,6 @@
3233
from PyQt5.QtWidgets import QMainWindow
3334
from PyQt5.QtWidgets import QMessageBox
3435
from PyQt5.QtWidgets import QInputDialog
35-
Config
3636

3737
logger = get_gui_logger()
3838

@@ -199,18 +199,15 @@ def on_test_button_clicked(self):
199199
"The individual value cannot be an empty string.", QMessageBox.Ok)
200200
return
201201

202-
# Calculate individual cost
203-
try:
204-
cost = self._test_individual_value(test_indiv_edit.text())
202+
cost = test_individual_value(parent=self,
203+
experiment_name=self._experiment_name,
204+
log_prefix="[EXPERIMENT_WINDOW]",
205+
indiv_value=test_indiv_edit.text(),
206+
config=Config.get_instance())
207+
208+
if cost:
205209
test_label_result = self._autogenerated_object.test_label_result
206210
test_label_result.setText(str(cost))
207-
except Exception, err:
208-
logger.error('[EXPERIMENT {0}] [TEST_BUTTON] - Error while evaluation individual. '
209-
'Check the expression to be correct. Error {1}'
210-
.format(self._experiment_name, err))
211-
QMessageBox.critical(self, "Test Individual",
212-
"Error while evaluation individual. Check the expression to be correct",
213-
QMessageBox.Ok)
214211

215212
def on_log_check_clicked(self):
216213
logger.debug('[EXPERIMENT {0}] [LOG_CHECK_CLICKED] - Executing on_log_check_clicked function'
@@ -733,13 +730,3 @@ def _update_experiment(self, cancelled):
733730
self._update_experiment_info()
734731
self._update_individuals_figure()
735732
self._update_scatter_chart()
736-
737-
def _test_individual_value(self, indiv_value):
738-
"""
739-
Evaluate an individual in order to check its correctness. If the evaluation
740-
throw any exception, it won't be handled in this method
741-
"""
742-
individual = Individual.generate(config=Config.get_instance(),
743-
rhs_value=indiv_value)
744-
callback = EvaluatorFactory.get_callback()
745-
return callback.cost(individual)

MLC/GUI/Experiment/FirstIndividualsManager.py

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
from MLC.GUI.Tables.ConfigTableModel import ConfigTableModel
2+
from MLC.GUI.util import test_individual_value
23
from MLC.Log.log import get_gui_logger
34
from MLC.individual.Individual import Individual
45
from MLC.mlc_parameters.mlc_parameters import Config
5-
from MLC.Population.Evaluation.EvaluatorFactory import EvaluatorFactory
6-
76
from MLC.Population.Creation.IndividualSelection import IndividualSelection
87
from MLC.Population.Creation.CreationFactory import CreationFactory
98
from PyQt5.QtWidgets import QInputDialog
@@ -38,8 +37,11 @@ def add_individual(self):
3837
return
3938

4039
indiv_value = indiv[0]
41-
try:
42-
self._test_individual_value(indiv_value)
40+
if test_individual_value(parent=self._parent,
41+
experiment_name=self._experiment_name,
42+
log_prefix="[FIRST_INDIVS_MANAGER]",
43+
indiv_value=indiv_value,
44+
config=Config.get_instance()):
4345
self._individuals.append(indiv_value)
4446
self._load_table()
4547

@@ -49,15 +51,6 @@ def add_individual(self):
4951
logger.info("[FIRST_INDIVS_MANAGER] Experiment {0} - "
5052
"Individual {1} was succesfully added"
5153
.format(self._experiment_name, indiv_value))
52-
except Exception, err:
53-
QMessageBox.critical(self._parent,
54-
"Invalid Individual",
55-
"Individual inserted is not a valid individual. "
56-
"Check the expression to be correct.")
57-
logger.error("[FIRST_INDIVS_MANAGER] Experiment {0} - "
58-
"Individual inserted is not a valid individual. "
59-
"Check the expression to be correct."
60-
.format(self._experiment_name, err))
6154

6255
def add_individuals_from_textfile(self):
6356
pass
@@ -71,7 +64,7 @@ def remove_individual(self, indiv_index):
7164
def get_gen_creator(self):
7265
"""
7366
Return an IndividualSelection creator if the user added individuals
74-
manually.
67+
manually.
7568
Return None if this was not the case
7669
"""
7770
if not self._individuals:
@@ -114,6 +107,7 @@ def _test_individual_value(self, indiv_value):
114107
Evaluate an individual in order to check its correctness. If the evaluation
115108
throw any exception, it won't be handled in this method
116109
"""
110+
LispTreeExpr.check_expression(indiv_value)
117111
individual = Individual.generate(config=Config.get_instance(),
118112
rhs_value=indiv_value)
119113
callback = EvaluatorFactory.get_callback()

MLC/GUI/util.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from MLC.Common.LispTreeExpr.LispTreeExpr import LispTreeExpr
2+
from MLC.Common.LispTreeExpr.LispTreeExpr import ExprException
3+
from MLC.individual.Individual import Individual
4+
from MLC.Log.log import get_gui_logger
5+
from MLC.Population.Evaluation.EvaluatorFactory import EvaluatorFactory
6+
from PyQt5.QtWidgets import QMessageBox
7+
8+
logger = get_gui_logger()
9+
10+
"""
11+
Utilities functions used in more than one class or python module
12+
"""
13+
14+
15+
def test_individual_value(parent, experiment_name, log_prefix, indiv_value, config):
16+
try:
17+
"""
18+
Evaluate an individual in order to check its correctness. Handle Exceptions
19+
"""
20+
LispTreeExpr.check_expression(indiv_value)
21+
individual = Individual.generate(config=config,
22+
rhs_value=indiv_value)
23+
callback = EvaluatorFactory.get_callback()
24+
return callback.cost(individual)
25+
except ExprException, err:
26+
# Print the error message returned in the exception,
27+
# removing the prefix ([EXPR_EXCEPTION]])
28+
QMessageBox.critical(parent,
29+
"Invalid Individual",
30+
"Individual inserted is not well-formed. "
31+
"Error Msg: {0}"
32+
.format(err.message[err.message.find(']') + 2:]))
33+
logger.error("{0} Experiment {1} - "
34+
"Individual inserted is not well-formed. "
35+
"Error Msg: {2}"
36+
.format(log_prefix, experiment_name,
37+
err.message[err.message.find(']') + 2:]))
38+
except Exception, err:
39+
QMessageBox.critical(parent,
40+
"Invalid Evaluation Script",
41+
"Check the evaluation script to be correct. "
42+
"Error Msg: {0}.".format(err))
43+
logger.error("{0} Experiment {1} - "
44+
"Individual inserted is not a valid individual. "
45+
"Check the evaluation script to be correct. "
46+
"Error Msg: {2}."
47+
.format(log_prefix, experiment_name, err))
48+
49+
return None

tests/mlc/common/lisp_tree_expr/test_expression_tree.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ def test_check_expression_complex_correct_plus_arguments_amount_5(self):
9292
expression = '(root (+ (* 2 3) 8))'
9393
self.assert_check_expression_without_exception(expression)
9494

95+
def test_check_expression_super_complex_correct_expression(self):
96+
expression = '(root (tanh (+ (tanh (+ (sin (+ (+ (- S0 (log 3.4232)) (- S0 (log -3.3987))) (- S0 (log 7.7256)))) (sin (- S0 (log 6.3053))))) (- S0 (log 2.7057)))))'
97+
self.assert_check_expression_without_exception(expression)
98+
99+
def test_check_expression_super_complex_incorrect_expression(self):
100+
expression = '(root (tanh (+ (tanh (+ (sin (+ (+ (- S0 (log 3.4232)) (- S0 (log -3.3987 123))) (- S0 (log 7.7256)))) (sin (- S0 (log 6.3053))))) (- S0 (log 2.7057)))))'
101+
self.assert_check_expression_with_exception(expression, OperationArgumentsAmountException)
102+
95103
def test_tree_depth_root(self):
96104
expression = '(root S0)'
97105
tree = LispTreeExpr(expression)

0 commit comments

Comments
 (0)