Skip to content

Commit fc7ceae

Browse files
committed
Merge branch 'master' into persist_board_configuration
Conflicts: MLC/api/MLCLocal.py tests/mlc/api/test_mlc.py
2 parents 4b0957c + 9373cff commit fc7ceae

24 files changed

+1662
-1349
lines changed

MLC/Application.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,6 @@ def _set_numpy_parameters(self):
7979
np.set_printoptions(threshold=np.inf)
8080
# Don't show scientific notation
8181
np.set_printoptions(suppress=True)
82-
# Transform printed warnings to real warnings
83-
np.seterr(all='raise')
8482

8583
def go(self, to_generation, from_generation=None, display_best=False):
8684
"""
@@ -155,9 +153,6 @@ def go(self, to_generation, from_generation=None, display_best=False):
155153
# emit app finish event
156154
self.__callbacks_manager.on_event(MLC_CALLBACKS.ON_FINISH)
157155

158-
# Return the numpy warning configuration to its original value
159-
np.seterr(all='warn')
160-
161156
def get_simulation(self):
162157
return self._simulation
163158

MLC/Common/LispTreeExpr/LispTreeExpr.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def __init__(self, expression):
2525
"[EXPR_EXCEPTION] Root node was not found. Expression: {0}"
2626
.format(expression))
2727

28+
2829
class TrailingTrashExprException(ExprException):
2930

3031
def __init__(self, expression):
@@ -122,9 +123,9 @@ def check_operands(expr):
122123

123124
if expr[pos] == '(':
124125
# The argument is another operator. Process it recursively
125-
argument_len = check_operands(expr[pos:])
126-
pos += argument_len
127-
if expr[pos] == ' ':
126+
argument_len = check_operands(expr[pos:])
127+
pos += argument_len
128+
if expr[pos] == ' ':
128129
pos += 1
129130
else:
130131
# The argument is a number or a sensor
@@ -143,7 +144,6 @@ def check_operands(expr):
143144
break
144145

145146
if arg_counter != expr_op["nbarg"]:
146-
print arg_counter
147147
raise OperationArgumentsAmountException(expr)
148148

149149
# The position always finished in the last bracket.
@@ -181,6 +181,8 @@ def visit_leaf_node(self, node):
181181
# First, replace the sensors
182182
visitor = Replace_Sensors_Visitor(sensor_replacement_list)
183183
self._root.accept(visitor)
184+
185+
# Transform printed warnings to real warnings
184186
return self._root.compute()
185187

186188
def get_root_node(self):

MLC/Common/LispTreeExpr/OperationNodes.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,15 @@ def simplify(self):
340340
return self
341341

342342
def compute(self):
343+
np.seterr(all='raise')
343344
if len(self._nodes) == 1:
344-
return self._nodes[0].compute()
345+
result = self._nodes[0].compute()
346+
np.seterr(all='warn')
347+
return result
345348

346-
return [node.compute() for node in self._nodes]
349+
result = [node.compute() for node in self._nodes]
350+
np.seterr(all='warn')
351+
return result
347352

348353
def formal(self):
349354
if len(self._nodes) == 1:

MLC/Common/PreevaluationManager.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,26 @@ def get_callback():
1818
"""
1919
# Check if the preevaluation is activated
2020
if Config.get_instance().getboolean('EVALUATOR', 'preevaluation'):
21-
module_name = Config.get_instance().get('EVALUATOR', 'preev_function')
21+
function_name = Config.get_instance().get('EVALUATOR', 'preev_function')
22+
module_name = "Preevaluation.{0}".format(function_name)
23+
24+
try:
25+
# WARNING: I am unloading manually the evaluation function module. I need to do this
26+
# because Python does not support module unloading and my evaluation functions are
27+
# all the same, so when one experiment loads his module, other project with the same
28+
# name of module won't be able to load yours
29+
preev_module = sys.modules["Preevaluation"]
30+
del sys.modules['Preevaluation']
31+
del preev_module
32+
lg.logger_.debug("[EV_FACTORY] Module {0} was removed"
33+
.format(sys.modules["Preevaluation"]))
34+
except KeyError, err:
35+
# If the module cannot be unload because it does not exists, continue
36+
pass
37+
2238
lg.logger_.debug('[PREEV_MANAGER] Importing module {0}'.format(module_name))
2339
try:
24-
module = importlib.import_module('Preevaluation.' + module_name)
40+
module = importlib.import_module(module_name)
2541
reload(module)
2642
return module
2743
except ImportError:

MLC/GUI/Autogenerated/autogenerated.py

Lines changed: 1084 additions & 1084 deletions
Large diffs are not rendered by default.

MLC/GUI/Autogenerated/mlc_qtcreator/experiment.ui

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -473,27 +473,26 @@
473473
<item>
474474
<widget class="QGroupBox" name="groupBox_3">
475475
<property name="title">
476-
<string>DB</string>
476+
<string>Generations</string>
477477
</property>
478478
<layout class="QVBoxLayout" name="verticalLayout_13">
479479
<item>
480-
<widget class="QPushButton" name="pushButton_3">
481-
<property name="text">
482-
<string>Create</string>
480+
<widget class="QPushButton" name="gen_cut_button">
481+
<property name="toolTip">
482+
<string>Remove generations ahead of the current generation</string>
483483
</property>
484-
</widget>
485-
</item>
486-
<item>
487-
<widget class="QPushButton" name="pushButton_4">
488484
<property name="text">
489485
<string>Cut</string>
490486
</property>
491487
</widget>
492488
</item>
493489
<item>
494-
<widget class="QPushButton" name="pushButton_8">
490+
<widget class="QPushButton" name="gen_start_over_button">
491+
<property name="toolTip">
492+
<string>Remove all the generations, maintaining only the last generation computed</string>
493+
</property>
495494
<property name="text">
496-
<string>Import</string>
495+
<string>Start Over</string>
497496
</property>
498497
</widget>
499498
</item>
@@ -1239,6 +1238,38 @@
12391238
</hint>
12401239
</hints>
12411240
</connection>
1241+
<connection>
1242+
<sender>gen_cut_button</sender>
1243+
<signal>clicked()</signal>
1244+
<receiver>ExperimentWindow</receiver>
1245+
<slot>on_gen_cut_button_clicked()</slot>
1246+
<hints>
1247+
<hint type="sourcelabel">
1248+
<x>835</x>
1249+
<y>309</y>
1250+
</hint>
1251+
<hint type="destinationlabel">
1252+
<x>480</x>
1253+
<y>283</y>
1254+
</hint>
1255+
</hints>
1256+
</connection>
1257+
<connection>
1258+
<sender>gen_start_over_button</sender>
1259+
<signal>clicked()</signal>
1260+
<receiver>ExperimentWindow</receiver>
1261+
<slot>on_gen_start_over_button_clicked()</slot>
1262+
<hints>
1263+
<hint type="sourcelabel">
1264+
<x>835</x>
1265+
<y>337</y>
1266+
</hint>
1267+
<hint type="destinationlabel">
1268+
<x>480</x>
1269+
<y>283</y>
1270+
</hint>
1271+
</hints>
1272+
</connection>
12421273
</connections>
12431274
<slots>
12441275
<slot>on_closed_dialog()</slot>
@@ -1266,5 +1297,7 @@
12661297
<slot>on_first_add_indiv_button_clicked()</slot>
12671298
<slot>on_first_remove_indiv_button_clicked()</slot>
12681299
<slot>on_first_add_indiv_from_textfile_button_clicked()</slot>
1300+
<slot>on_gen_cut_button_clicked()</slot>
1301+
<slot>on_gen_start_over_button_clicked()</slot>
12691302
</slots>
12701303
</ui>

MLC/GUI/Experiment/ExperimentWindow.py

Lines changed: 87 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
from MLC.Population.Population import Population
2525
from PyQt5.QtCore import pyqtSignal
2626
from PyQt5.QtCore import QFileSystemWatcher
27-
# from PyQt5.QtCore import QHeaderView
2827
from PyQt5.QtCore import Qt
2928
from PyQt5.QtCore import QUrl
3029
from PyQt5.QtGui import QDesktopServices
@@ -417,6 +416,83 @@ def on_first_remove_indiv_button_clicked(self):
417416
.format(self._experiment_name))
418417
self._first_indivs_manager.remove_individual()
419418

419+
def on_gen_cut_button_clicked(self):
420+
logger.debug('[EXPERIMENT {0}] [GEN_CUT_BUTTON] - '
421+
'Executing on_gen_cut_button_clicked function'
422+
.format(self._experiment_name))
423+
experiment_info = self._mlc_local.get_experiment_info(self._experiment_name)
424+
number_of_gens = experiment_info["generations"]
425+
426+
amount_of_gen_losts = number_of_gens - self._current_gen + 1
427+
response = QMessageBox.warning(self, "Cut Generations",
428+
"{0} generations will be lost with this operation. "
429+
"Do you really want to continue?"
430+
.format(amount_of_gen_losts),
431+
QMessageBox.Yes | QMessageBox.No,
432+
QMessageBox.No)
433+
434+
if response == QMessageBox.Yes:
435+
logger.info("[GEN_CUT_BUTTON] Proceed to remove {0} generations (From Generation N°{1} onwards)"
436+
.format(amount_of_gen_losts, self._current_gen))
437+
self._mlc_local.remove_generations_from(self._experiment_name,
438+
self._current_gen)
439+
last_gen_removed = self._current_gen
440+
# Recalculate the amount of generations in the project
441+
experiment_info = self._mlc_local.get_experiment_info(self._experiment_name)
442+
self._current_gen = experiment_info["generations"]
443+
self._update_individuals_per_generation_list()
444+
self._update_experiment_info()
445+
self._update_individuals_figure()
446+
self._update_scatter_chart()
447+
448+
QMessageBox.information(self, "Cut Generations",
449+
"{0} Generations were succesfully removed (From N°{1} onwards)"
450+
.format(amount_of_gen_losts, last_gen_removed))
451+
452+
def on_gen_start_over_button_clicked(self):
453+
logger.debug('[EXPERIMENT {0}] [GEN_START_OVER_BUTTON] - '
454+
'Executing on_gen_start_over_button_clicked function'
455+
.format(self._experiment_name))
456+
457+
response = QMessageBox.warning(self, "Start Over",
458+
"Except for Generation N°{0}, all generations will be removed. "
459+
"Do you really want to continue?"
460+
.format(self._current_gen),
461+
QMessageBox.Yes | QMessageBox.No,
462+
QMessageBox.No)
463+
464+
if response == QMessageBox.Yes:
465+
chosen_generation = self._current_gen
466+
logger.info("[GEN_START_OVER] Removing all the experiment generations "
467+
"except for generation N°{0}".format(self._current_gen))
468+
469+
experiment_info = self._mlc_local.get_experiment_info(self._experiment_name)
470+
number_of_gens = experiment_info["generations"]
471+
472+
if self._current_gen != number_of_gens:
473+
self._mlc_local.remove_generations_from(self._experiment_name,
474+
self._current_gen + 1)
475+
476+
if self._current_gen != 1:
477+
self._mlc_local.remove_generations_to(self._experiment_name,
478+
self._current_gen - 1)
479+
480+
# Recalculate the amount of generations in the project
481+
experiment_info = self._mlc_local.get_experiment_info(self._experiment_name)
482+
self._current_gen = experiment_info["generations"]
483+
self._update_individuals_per_generation_list()
484+
self._update_experiment_info()
485+
self._update_individuals_figure()
486+
self._update_scatter_chart()
487+
488+
QMessageBox.information(self, "Star Over Generations",
489+
"Experiment was succesfully pruned. Past Generation "
490+
"N°{0} is the only generation of the experiment"
491+
.format(chosen_generation))
492+
493+
494+
################################### VIEW AND MODEL METHODS #########################################
495+
420496
def _config_table_edited(self, left, right):
421497
config_table = self._autogenerated_object.config_table
422498
table_model = config_table.model()
@@ -626,18 +702,12 @@ def _update_experiment_info(self):
626702
else:
627703
self._current_gen = 0
628704
gen_count_group.setTitle("Generation: 0/0")
705+
db_view = self._autogenerated_object.db_view
706+
db_view.setModel(None)
629707

630708
def _update_individuals_figure(self):
709+
chart_layout = self._autogenerated_object.chart_layout
631710
if self._current_gen != 0:
632-
chart_layout = self._autogenerated_object.chart_layout
633-
634-
# Matplotlib graphs
635-
# indiv_canvas = CostPerIndividualCanvas(indiv_graph_frame, width=5, height=4, dpi=85)
636-
# indiv_canvas.set_costs(current_generation.get_costs())
637-
# indiv_canvas.set_xlabel('Individuals')
638-
# indiv_canvas.set_ylabel('Costs')
639-
# indiv_canvas.set_title('Cost Per Individual')
640-
# indiv_canvas.compute_initial_figure(self._autogenerated_object.log_check.isChecked())
641711

642712
# Draw current generation
643713
current_generation = self._mlc_local.get_generation(self._experiment_name, self._current_gen)
@@ -664,13 +734,18 @@ def _update_individuals_figure(self):
664734
costs = gen.get_costs()
665735
indiv_chart.add_data(samples, costs, color=Qt.blue, line_width=1)
666736

667-
indiv_canvas = indiv_chart.get_widget()
668-
669737
# Remove all previous widgets before rendering again
670738
for i in reversed(range(chart_layout.count())):
671739
chart_layout.itemAt(i).widget().setParent(None)
740+
672741
# Add the Indiv Canvas
742+
indiv_canvas = indiv_chart.get_widget()
673743
chart_layout.addWidget(indiv_canvas)
744+
else:
745+
# Remove all previous widgets before rendering again
746+
for i in reversed(range(chart_layout.count())):
747+
chart_layout.itemAt(i).widget().setParent(None)
748+
chart_layout.addWidget(self._autogenerated_object.textEdit_2)
674749

675750
def _reload_experiment_config(self, some_string):
676751
logger.debug('[EXPERIMENT {0}] [EXPERIMENT_CONF_FILE_CHANGED] - '

MLC/GUI/Experiment/FirstIndividualsManager.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -226,14 +226,3 @@ def _load_table(self):
226226
table_model.set_editable_columns([1])
227227
table_model.set_data_changed_callback(self.modify_individual)
228228
table_model.sort_by_col(0)
229-
230-
def _test_individual_value(self, indiv_value):
231-
"""
232-
Evaluate an individual in order to check its correctness. If the evaluation
233-
throw any exception, it won't be handled in this method
234-
"""
235-
LispTreeExpr.check_expression(indiv_value)
236-
individual = Individual.generate(config=Config.get_instance(),
237-
rhs_value=indiv_value)
238-
callback = EvaluatorFactory.get_callback()
239-
return callback.cost(individual)

MLC/Population/Evaluation/EvaluatorFactory.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,31 @@
99
class EvaluatorFactory(object):
1010
@staticmethod
1111
def get_callback():
12-
module_name = Config.get_instance().get('EVALUATOR', 'evaluation_function')
12+
function_name = Config.get_instance().get('EVALUATOR', 'evaluation_function')
13+
module_name = 'Evaluation.{0}'.format(function_name)
14+
15+
try:
16+
# WARNING: I am unloading manually the evaluation function module. I need to do this
17+
# because Python does not support module unloading and my evaluation functions are
18+
# all the same, so when one experiment loads his module, other project with the same
19+
# name of module won't be able to load yours
20+
ev_module = sys.modules["Evaluation"]
21+
del sys.modules['Evaluation']
22+
del ev_module
23+
lg.logger_.debug("[EV_FACTORY] Module {0} was removed".format(sys.modules["Evaluation"]))
24+
except KeyError, err:
25+
# If the module cannot be unload because it does not exists, continue
26+
pass
27+
1328
lg.logger_.debug('[EV_FACTORY] Importing module {0}'.format(module_name))
1429
try:
15-
module = importlib.import_module('Evaluation.' + module_name)
30+
# lg.logger_.debug("[EV_FACTORY] Sys.path: {0}".format(sys.path))
31+
module = importlib.import_module(module_name)
1632
reload(module)
1733
return module
18-
except ImportError:
19-
lg.logger_.debug("[EV_FACTORY] Evaluation function doesn't exists. " +
20-
"Aborting program...")
34+
except ImportError, err:
35+
lg.logger_.debug("[EV_FACTORY] Evaluation function doesn't exists. "
36+
"Aborting program. Error Msg: {0}".format(err))
2137
sys.exit(-1)
2238

2339
@staticmethod

0 commit comments

Comments
 (0)