From 84a27f5ea8a49313788ce6ae07a5487fa5817cf6 Mon Sep 17 00:00:00 2001 From: "Eric O. LEBIGOT (EOL)" Date: Sun, 14 Aug 2016 00:57:52 +0200 Subject: [PATCH] =?UTF-8?q?Working=20sum(=E2=80=A6).=20The=20speed-up=20is?= =?UTF-8?q?=20impressive:=205k=20numbers=20went=20from=2017=20s=20to=20a?= =?UTF-8?q?=20fraction=20of=20a=20second.=20100k=20numbers=20are=201.5=20s?= =?UTF-8?q?.=201,000,000=20numbers=20are=2015=20s.=20Linear=20time=20compl?= =?UTF-8?q?exity=20is=20observed,=20indeed!=20:)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- uncertainties/core.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/uncertainties/core.py b/uncertainties/core.py index 1bba6062..cdacf87e 100644 --- a/uncertainties/core.py +++ b/uncertainties/core.py @@ -239,7 +239,7 @@ def to_affine_scalar(x): if isinstance(x, CONSTANT_TYPES): # No variable => no derivative: - return Variable(x, []) + return Variable(x, NestedLinearCombination()) # Case of lists, etc. raise NotUpcast("%s cannot be converted to a number with" @@ -707,7 +707,8 @@ def f_with_affine_output(*args, **kwargs): # The function now returns the necessary linear approximation # to the function: - return AffineScalarFunc(f_nominal_value, linear_part) + return AffineScalarFunc(f_nominal_value, + NestedLinearCombination(linear_part)) f_with_affine_output = set_doc("""\ Version of %s(...) that returns an affine approximation @@ -1435,7 +1436,9 @@ def signif_dgt_to_limit(value, num_signif_d): # !!!!!!!! This creates a copy of the list, when the expression is # built: I should probably just store linear_combo. !!!!!!! SAME for # a new FlatLinearCombination, that I would access explicitly between -# class that know how it works. +# class that know how it works. Using slots should be quite cheap in +# memory. BUT I would pay with attribute access, when doing +# calculations. class NestedLinearCombination(list): """ List of (float_coefficient, NestedLinearCombination) or @@ -1475,17 +1478,22 @@ def expand_and_empty(self): # remaining (and whose size can temporarily grow): main_factor, main_expr = self.pop() + # print "MAINS", main_factor, main_expr #!!!!!!!!!!!! + if isinstance(main_expr, NestedLinearCombination): - for (factor, expr) in main_expr.iteritems(): + for (factor, expr) in main_expr: # The main_factor is applied to expr: self.append((main_factor*factor, expr)) else: # We directly have an expanded linear combination - for (factor, var) in main_expr.iteritems(): + for (var, factor) in main_expr.iteritems(): derivatives[var] += main_factor*factor + # print "DERIV", derivatives #!!!!!!!!!!! + + return derivatives class AffineScalarFunc(object): @@ -1614,6 +1622,7 @@ def derivatives(self): # Attempts to get the contribution of a variable that the # function does not depend on raise a KeyError: self._linear_part.default_factory = None + return self._linear_part ############################################################ @@ -1711,6 +1720,10 @@ def error_components(self): for (variable, derivative) in self.derivatives.iteritems(): + # print "TYPE", type(variable), type(derivative) #!!!!!!!!!!!! + + + # Individual standard error due to variable: # 0 is returned even for a NaN derivative (in this case no