Skip to content

Commit 529889e

Browse files
committed
Added numpy warning tests
* Added a tree for the LispTreeExpr class and another for the whole project #61
1 parent e5c41e1 commit 529889e

File tree

8 files changed

+226
-9
lines changed

8 files changed

+226
-9
lines changed

templates/toy_problem.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,13 @@ def individual_data(indiv):
5555

5656
def cost(indiv):
5757
x, y, y2, mlc_y3 = individual_data(indiv)
58-
cost_mlc_y3 = None
59-
try:
60-
cost_mlc_y3 = float(np.sum((mlc_y3 - y2)**2))
61-
except FloatingPointError, err:
62-
np.seterr(all='ignore')
63-
cost_mlc_y3 = float(np.sum((mlc_y3 - y2)**2))
64-
np.seterr(all='raise')
58+
59+
# Deactivate the numpy warnings, because this sum raise an overflow
60+
# Runtime warning from time to time
61+
np.seterr(all='ignore')
62+
cost_mlc_y3 = float(np.sum((mlc_y3 - y2)**2))
63+
np.seterr(all='warn')
64+
6565
return cost_mlc_y3
6666

6767

tests/default_test_configuration.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[LOGGING]
2-
logmode = console
2+
logmode = file
33

44
[POPULATION]
55
# Population size. This paramater can be a number or a numpy array

tests/mlc/application/__init__.py

Whitespace-only changes.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
[LOGGING]
2+
logmode = file
3+
4+
[POPULATION]
5+
# Population size. This paramater can be a number or a numpy array
6+
size = 10
7+
sensors = 1
8+
sensor_spec = false
9+
sensor_list = 1, 9, 4
10+
controls = 1
11+
sensor_prob = 0.33
12+
leaf_prob = 0.3
13+
range = 10
14+
precision = 4
15+
# Numpy arrange
16+
opsetrange = 1:10
17+
formal = 1
18+
end_character =
19+
individual_type = tree
20+
21+
[GP]
22+
# GP algortihm (CHANGE IF YOU KNOW WHAT YOU DO)
23+
maxdepth = 15
24+
maxdepthfirst = 5
25+
mindepth = 2
26+
mutmindepth = 2
27+
mutmaxdepth = 15
28+
mutsubtreemindepth = 2
29+
generation_method = mixed_ramped_gauss
30+
gaussigma = 3
31+
# Numpy arange
32+
ramp = 2:9
33+
maxtries = 10
34+
mutation_types = 1:5
35+
36+
[OPTIMIZATION]
37+
# Optimization parameters
38+
elitism = 10
39+
probrep = 0.1
40+
probmut = 0.4
41+
probcro = 0.5
42+
selectionmethod = tournament
43+
tournamentsize = 7
44+
lookforduplicates = true
45+
simplify = false
46+
# Numpy array
47+
cascade = 1,1
48+
49+
[EVALUATOR]
50+
# Evaluator
51+
# evaluation_method = standalone_function
52+
# evaluation_method = standalone_files
53+
evaluation_method = mfile_standalone
54+
evaluation_function = numpy_warnings_ev_script
55+
indfile = ind.dat
56+
Jfile = J.dat
57+
# exchangedir = fullfile(pwd,evaluator0)
58+
evaluate_all = 0
59+
ev_again_best = false
60+
ev_again_nb = 5
61+
ev_again_times = 5
62+
artificialnoise = 0
63+
execute_before_evaluation =
64+
badvalue = 1e36
65+
badvalues_elim = first
66+
%badvalues_elim = none
67+
%badvalues_elim = all
68+
preevaluation = false
69+
preev_function = default
70+
problem_variables.gamma = 0.1
71+
72+
[BEHAVIOUR]
73+
## MLC behaviour
74+
verbose = 2
75+
fgen = 250
76+
stopongraph = false
77+
showeveryitbest = true
78+
save = false
79+
saveincomplete = 1
80+
savedir = test_first_experiment.mlc
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import numpy as np
4+
import MLC.Log.log as lg
5+
import matplotlib.pyplot as plt
6+
import sys
7+
import time
8+
9+
from MLC.mlc_parameters.mlc_parameters import Config
10+
from PyQt5.QtCore import Qt
11+
12+
13+
def individual_data(indiv):
14+
x = np.linspace(-10.0, 10.0, num=201)
15+
y = np.tanh(x**3 - x**2 - 1)
16+
17+
# FIXME: Added timeout to visualize
18+
# time.sleep(0.5)
19+
20+
config = Config.get_instance()
21+
# artificial_noise = self._config.getint('EVALUATOR', 'artificialnoise')
22+
23+
# In this test we have no noise by config file. But, if this were the
24+
# case, we would a have problem because the random of MATLAB is not
25+
# the random of Python :(
26+
# WORKAROUND: Generate the noise in matlab and process it in python
27+
28+
# MAKE SOME NOISE!!!
29+
# noise = eng.eval('rand(length(zeros(1, ' + str(len(x)) + ')))-0.5')
30+
# np_noise = np.array([s for s in noise[0]])
31+
# y2 = y + np_noise * 500 * artificial_noise
32+
33+
y2 = y
34+
35+
# Force a numpy warning BEFORE the LispTreeExpr calculation
36+
np.cos(np.inf)
37+
38+
if isinstance(indiv.get_formal(), str):
39+
formal = indiv.get_formal().replace('S0', 'x')
40+
else:
41+
# toy problem support for multiple controls
42+
formal = indiv.get_formal()[0].replace('S0', 'x')
43+
44+
# Calculate J like the sum of the square difference of the
45+
# functions in every point
46+
47+
lg.logger_.debug('[POP][TOY_PROBLEM] Individual Formal: ' + formal)
48+
mlc_y3 = indiv.get_tree().calculate_expression([x])
49+
50+
# If the expression doesn't have the term 'x',
51+
# the eval returns a value (float) instead of an array.
52+
# In that case transform it to an array
53+
if type(mlc_y3) == float:
54+
mlc_y3 = np.repeat(mlc_y3, len(x))
55+
56+
# Force a numpy warning AFTER the LispTreeExpr calculation
57+
np.cos(np.inf)
58+
59+
return x, y, y2, mlc_y3
60+
61+
62+
def cost(indiv):
63+
x, y, y2, mlc_y3 = individual_data(indiv)
64+
cost_mlc_y3 = None
65+
try:
66+
cost_mlc_y3 = float(np.sum((mlc_y3 - y2)**2))
67+
except FloatingPointError, err:
68+
np.seterr(all='ignore')
69+
cost_mlc_y3 = float(np.sum((mlc_y3 - y2)**2))
70+
np.seterr(all='raise')
71+
return cost_mlc_y3
72+
73+
74+
def show_best(index, generation, indiv, cost, block=True):
75+
x, y, y2, mlc_y3 = individual_data(indiv)
76+
# FIXME: Absolute only makes sense if we're working with complex numbers. It's not the case...
77+
y4 = np.sqrt((y - mlc_y3)**2 / (1 + np.absolute(x**2)))
78+
79+
fig = plt.figure()
80+
# Put figure window on top of all other windows
81+
fig.canvas.manager.window.setWindowModality(Qt.ApplicationModal)
82+
83+
plt.suptitle("Generation N#{0} - Individual N#{1}\n"
84+
"Cost: {2}\n Formal: {3}".format(generation,
85+
index,
86+
cost,
87+
indiv.get_formal()))
88+
plt.subplot(2, 1, 1)
89+
plt.plot(x, y, x, y2, '*', x, mlc_y3)
90+
91+
plt.subplot(2, 1, 2)
92+
plt.plot(x, y4, '*r')
93+
plt.yscale('log')
94+
plt.show(block=block)
Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,39 @@ def setUpClass(cls):
4646
def tearDownClass(cls):
4747
# Erase the MLC workspace dir of this tests
4848
shutil.rmtree(ApplicationTest.workspace_dir)
49-
pass
49+
50+
def test_numpy_warnings_on_evaluation_script(self):
51+
# MLC catches the numpy warnings and notify them in its log. By doing this,
52+
# numpy warnings are set to throw exception. The idea of this test is to
53+
# prove that this behaviour (numpy warnings as Exceptions) does not affect
54+
# the evaluation scripts
55+
experiment_name = "numpy_warnings"
56+
57+
numpy_ev_script = "numpy_warnings_ev_script.py"
58+
numpy_ev_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), numpy_ev_script)
59+
60+
numpy_config = "numpy_warnings_config.ini"
61+
numpy_config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), numpy_config)
62+
63+
ApplicationTest.mlc_local.new_experiment(experiment_name=experiment_name,
64+
experiment_configuration=numpy_config_path,
65+
evaluation_script=numpy_ev_path)
66+
67+
Config.get_instance().set("EVALUATOR", "evaluation_function", "numpy_warnings_ev_script")
68+
69+
ApplicationTest.mlc_local.open_experiment(experiment_name)
70+
try:
71+
ApplicationTest.mlc_local.go(experiment_name=experiment_name,
72+
to_generation=2,
73+
from_generation=0,
74+
callbacks={})
75+
except FloatingPointError:
76+
self.assertEquals(True, False)
77+
78+
ApplicationTest.mlc_local.close_experiment(experiment_name)
79+
ApplicationTest.mlc_local.delete_experiment(experiment_name)
80+
81+
self.assertEquals(True, True)
5082

5183
def test_callback_on_evaluate(self):
5284
with saved(Config.get_instance()) as config:
File renamed without changes.

tests/mlc/common/lisp_tree_expr/test_expression_tree.py renamed to tests/mlc/common/LispTreeExpr/test_expression_tree.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,17 @@ def test_tree_subtree(self):
148148
self.assertNode(subtree_1, depth=3, childs=1, expr_index=19)
149149
self.assertNode(subtree_1._nodes[0], depth=3, childs=0, expr_index=24)
150150

151+
def test_do_not_raise_exception_when_numpy_warning_appear(self):
152+
# This expression raise a numpy warning
153+
expression = '(root (cos (exp 1e20)))'
154+
tree = LispTreeExpr(expression)
155+
156+
try:
157+
tree.calculate_expression(sensor_replacement_list=[])
158+
self.assertEquals(True, True)
159+
except FloatingPointError:
160+
self.assertEquals(True, False)
161+
151162
def assertNode(self, node, depth, childs, expr_index):
152163
self.assertEquals(node.get_depth(), depth)
153164
self.assertEquals(node.get_expr_index(), expr_index)

0 commit comments

Comments
 (0)