Skip to content

Commit c31d174

Browse files
committed
Fixes in Division_Node operation
* There were problems in both MATLAB and Python implementations added in the previous commit * Added a bug folder including some scripts to reproduce the precision problems reported in previous issues #27
1 parent 7de62d6 commit c31d174

File tree

12 files changed

+610
-684
lines changed

12 files changed

+610
-684
lines changed

MLC/Common/Lisp_Tree_Expr/Operation_Nodes.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import math
21
import importlib
32

43
import MLC.Log.log as lg
@@ -108,11 +107,11 @@ def formal(self):
108107

109108
def _process_division(self, dividend, divisor):
110109
if type(divisor) == np.ndarray:
111-
divisor = [Division_Node.PROTECTION if abs(x) < Division_Node.PROTECTION else x for x in divisor]
112-
return np.sign(divisor) * dividend / np.asarray(divisor)
110+
new_divisor = [Division_Node.PROTECTION if np.abs(x) < Division_Node.PROTECTION else np.abs(x) for x in divisor]
111+
return np.sign(divisor) * dividend / np.asarray(new_divisor)
113112
else:
114113
if abs(divisor) < Division_Node.PROTECTION:
115-
return dividend / Division_Node.PROTECTION
114+
return np.sign(divisor) * dividend / Division_Node.PROTECTION
116115

117116
return dividend / divisor
118117

@@ -149,7 +148,7 @@ def formal(self):
149148

150149
def op_simplify(self):
151150
if not self._nodes[0].is_sensor():
152-
arg = math.sin(float(self._nodes[0].to_string()))
151+
arg = np.sin(float(self._nodes[0].to_string()))
153152
return Leaf_Node(process_float(arg))
154153
else:
155154
return self
@@ -168,7 +167,7 @@ def formal(self):
168167

169168
def op_simplify(self):
170169
if not self._nodes[0].is_sensor():
171-
arg = math.cos(float(self._nodes[0].to_string()))
170+
arg = np.cos(float(self._nodes[0].to_string()))
172171
return Leaf_Node(process_float(arg))
173172
else:
174173
return self
@@ -189,7 +188,7 @@ def formal(self):
189188

190189
def _process_arg(self, arg):
191190
if type(arg) == np.ndarray:
192-
return [Logarithm_Node.PROTECTION if abs(x) < Logarithm_Node.PROTECTION else abs(x) for x in arg]
191+
return [Logarithm_Node.PROTECTION if np.abs(x) < Logarithm_Node.PROTECTION else np.abs(x) for x in arg]
193192
else:
194193
if abs(arg) < Logarithm_Node.PROTECTION:
195194
return Logarithm_Node.PROTECTION
@@ -199,9 +198,9 @@ def _process_arg(self, arg):
199198
def op_simplify(self):
200199
if not self._nodes[0].is_sensor():
201200
if float(self._nodes[0].to_string()) < Logarithm_Node.SIMPLIFY_PROTECTION:
202-
arg = math.log(Logarithm_Node.SIMPLIFY_PROTECTION)
201+
arg = np.log(Logarithm_Node.SIMPLIFY_PROTECTION)
203202
else:
204-
arg = math.log(float(self._nodes[0].to_string()))
203+
arg = np.log(float(self._nodes[0].to_string()))
205204

206205
return Leaf_Node(process_float(arg))
207206
else:
@@ -223,9 +222,9 @@ def op_simplify(self):
223222
if not self._nodes[0].is_sensor():
224223
lg.logger_.debug("[EXP NODE] Value: " + self._nodes[0].to_string())
225224
try:
226-
arg = math.exp(float(self._nodes[0].to_string()))
225+
arg = np.exp(float(self._nodes[0].to_string()))
227226
except OverflowError:
228-
# FIXME: See what to do with this expression, because there are problems with
227+
# FIXME: See what to do with this expression, because there are problems when
229228
# an infinite value is the argumento of a sinusoidal function
230229
return Leaf_Node(process_float(float("inf")))
231230

@@ -247,7 +246,7 @@ def formal(self):
247246

248247
def op_simplify(self):
249248
if not self._nodes[0].is_sensor():
250-
arg = math.tanh(float(self._nodes[0].to_string()))
249+
arg = np.tanh(float(self._nodes[0].to_string()))
251250
return Leaf_Node(process_float(arg))
252251
else:
253252
return self

MLC/Scripts/Evaluation/toy_problem.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,7 @@
88

99

1010
def individual_data(indiv):
11-
x = np.arange(-10, 10 + 0.1, 0.1)
12-
# FIXME: Numpy precision it's driving me up the wall. It doesn't put a zero
13-
# in the middle element of the array (put a extremely small number instead).
14-
# That generates problems with the division operation
15-
x[len(x) / 2] = 0
11+
x = np.linspace(-10.0, 10.0, num=201)
1612
y = np.tanh(x**3 - x**2 - 1)
1713

1814
eng = MatlabEngine.engine()

MLC/Scripts/Evaluation/toy_problem_python_ev.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@
77

88

99
def individual_data(indiv):
10-
x = np.arange(-10, 10 + 0.1, 0.1)
11-
# FIXME: Numpy precision it's driving me up the wall. It doesn't put a zero
12-
# in the middle element of the array (put a extremely small number instead).
13-
# That generates problems with the division operation
14-
x[len(x) / 2] = 0
10+
x = np.linspace(-10.0, 10.0, num=201)
1511
y = np.tanh(x**3 - x**2 - 1)
1612

1713
config = Config.get_instance()

bugs/precision_bug/expr_test.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import sys
2+
sys.path.append("../..")
3+
import binascii
4+
import numpy as np
5+
import struct
6+
import MLC.Log.log as lg
7+
8+
from MLC.Common.Lisp_Tree_Expr.Lisp_Tree_Expr import Lisp_Tree_Expr
9+
from MLC.Log.log import set_logger
10+
from MLC.mlc_parameters.mlc_parameters import Config
11+
12+
13+
def initialize_config():
14+
config = Config.get_instance()
15+
config.read('../conf/configuration.ini')
16+
return config
17+
18+
# Set printable resolution (don't alter numpy interval resolution)
19+
np.set_printoptions(precision=9)
20+
# Show full arrays, no matter what size do they have
21+
np.set_printoptions(threshold=np.inf)
22+
# Don't show scientific notation
23+
np.set_printoptions(suppress=True)
24+
25+
initialize_config()
26+
set_logger('console')
27+
28+
# Full expression
29+
expr6 = "(root (cos (exp (- -6.3726 (* -7.1746 S0)))))"
30+
expr61 = "(root (exp (- -6.3726 (* -7.1746 S0))))"
31+
expr612 = "(root (- -6.3726 (* -7.1746 S0)))"
32+
33+
tree = Lisp_Tree_Expr(expr612)
34+
x = np.linspace(-10.0, 10.0, num=201)
35+
mlc_y = tree.calculate_expression([x])
36+
37+
# Calculate the Mean squared error
38+
y = np.tanh(x**3 - x**2 - 1)
39+
evaluation = float(np.sum((mlc_y - y)**2))
40+
41+
# print mlc_y
42+
with open("./costs_python.txt", "w") as f:
43+
for elem in mlc_y:
44+
f.write("%50.50f\n" % elem)
45+
46+
print evaluation
47+
print np.sum(mlc_y)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
close all;
2+
clear all;
3+
4+
%--------------------- %
5+
6+
x = -10:0.1:10;
7+
% m = 'exp(((-6.3726) - ((-7.1746) .* S0)))';
8+
m = '((-6.3726) - ((-7.1746) .* S0))';
9+
y = tanh(x.^3-x.^2-1);
10+
m = strrep(m, 'S0', 'x'); y2=eval(m); J=sum((y2-y).^2); fprintf('%.10f\n', J);
11+
12+
filename = './costs_matlab.txt';
13+
file = fopen(filename, 'w');
14+
15+
for i=1:length(x)
16+
fprintf(file, '%50.50f\n', y2(i));
17+
end
18+
19+
fclose(file);

main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def main():
2222

2323
eng = MatlabEngine.engine()
2424
config = initialize_config()
25-
# MatlabEngine.load_random_values("./tests/integration_tests/matlab_randoms.txt")
25+
MatlabEngine.load_random_values("./tests/integration_tests/matlab_randoms.txt")
2626

2727
# Create the MLC2 object and store it in the workspace. With this
2828
# feature we will be able to call every function of the MATLAB code

matlab_code/MLC_tools/my_div.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
b=arg1 ./ arg2;
99
else
1010
inverse_protect_array = ~protect_array;
11-
valid_elements = arg2 .* inverse_protect_array;
11+
valid_elements = abs(arg2) .* inverse_protect_array;
1212
non_valid_elements = protect_array .* protection;
1313
new_arg2 = valid_elements + non_valid_elements;
1414
b = sign_array .* arg1 ./ new_arg2;

tests/integration_tests/test_basic/configuration.ini

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ cascade = 1,1
5151
# evaluation_method = standalone_function
5252
# evaluation_method = standalone_files
5353
evaluation_method = mfile_standalone
54-
# evaluation_function = toy_problem
55-
evaluation_function = toy_problem_python_ev
54+
evaluation_function = toy_problem
55+
# evaluation_function = toy_problem_python_ev
5656
indfile = ind.dat
5757
Jfile = J.dat
5858
# exchangedir = fullfile(pwd,evaluator0)

0 commit comments

Comments
 (0)