From 97fd3d5fc6e59330aad2475129065b29897515b6 Mon Sep 17 00:00:00 2001 From: Jean-Philippe ARGAUD Date: Wed, 15 May 2019 21:18:32 +0200 Subject: [PATCH] Improve multisteps KF-like analysis by avoiding dual storage --- .../daAlgorithms/EnsembleKalmanFilter.py | 13 ++++++++----- .../daAlgorithms/ExtendedKalmanFilter.py | 13 ++++++++----- src/daComposant/daAlgorithms/KalmanFilter.py | 10 ++++++---- .../daAlgorithms/UnscentedKalmanFilter.py | 16 ++++++++++------ src/daComposant/daCore/Aidsm.py | 7 ++++--- src/daComposant/daCore/BasicObjects.py | 15 +++++++++++++-- src/daComposant/daCore/Interfaces.py | 5 +++-- 7 files changed, 52 insertions(+), 27 deletions(-) diff --git a/src/daComposant/daAlgorithms/EnsembleKalmanFilter.py b/src/daComposant/daAlgorithms/EnsembleKalmanFilter.py index 9448ec4..3ec8099 100644 --- a/src/daComposant/daAlgorithms/EnsembleKalmanFilter.py +++ b/src/daComposant/daAlgorithms/EnsembleKalmanFilter.py @@ -140,11 +140,14 @@ class ElementaryAlgorithm(BasicObjects.Algorithm): if hasattr(Q,"asfullmatrix"): Qn = Q.asfullmatrix(__n) else: Qn = Q # - self.StoredVariables["Analysis"].store( Xb.A1 ) - if self._toStore("APosterioriCovariance"): - self.StoredVariables["APosterioriCovariance"].store( Pn ) - covarianceXa = Pn - Xa = XaMin = Xb + if len(self.StoredVariables["Analysis"])==0 or not self._parameters["nextStep"]: + self.StoredVariables["Analysis"].store( numpy.ravel(Xb) ) + if self._toStore("APosterioriCovariance"): + self.StoredVariables["APosterioriCovariance"].store( Pn ) + covarianceXa = Pn + # + Xa = Xb + XaMin = Xb previousJMinimum = numpy.finfo(float).max # # Predimensionnement diff --git a/src/daComposant/daAlgorithms/ExtendedKalmanFilter.py b/src/daComposant/daAlgorithms/ExtendedKalmanFilter.py index bf3a830..dfcb3c5 100644 --- a/src/daComposant/daAlgorithms/ExtendedKalmanFilter.py +++ b/src/daComposant/daAlgorithms/ExtendedKalmanFilter.py @@ -127,11 +127,14 @@ class ElementaryAlgorithm(BasicObjects.Algorithm): Xn = Xb Pn = B # - self.StoredVariables["Analysis"].store( Xn.A1 ) - if self._toStore("APosterioriCovariance"): - self.StoredVariables["APosterioriCovariance"].store( Pn.asfullmatrix(Xn.size) ) - covarianceXa = Pn - Xa = XaMin = Xn + if len(self.StoredVariables["Analysis"])==0 or not self._parameters["nextStep"]: + self.StoredVariables["Analysis"].store( numpy.ravel(Xn) ) + if self._toStore("APosterioriCovariance"): + self.StoredVariables["APosterioriCovariance"].store( Pn.asfullmatrix(Xn.size) ) + covarianceXa = Pn + # + Xa = Xn + XaMin = Xn previousJMinimum = numpy.finfo(float).max # for step in range(duration-1): diff --git a/src/daComposant/daAlgorithms/KalmanFilter.py b/src/daComposant/daAlgorithms/KalmanFilter.py index 08210fd..4114270 100644 --- a/src/daComposant/daAlgorithms/KalmanFilter.py +++ b/src/daComposant/daAlgorithms/KalmanFilter.py @@ -118,10 +118,12 @@ class ElementaryAlgorithm(BasicObjects.Algorithm): Xn = Xb Pn = B # - self.StoredVariables["Analysis"].store( Xn.A1 ) - if self._toStore("APosterioriCovariance"): - self.StoredVariables["APosterioriCovariance"].store( Pn.asfullmatrix(Xn.size) ) - covarianceXa = Pn + if len(self.StoredVariables["Analysis"])==0 or not self._parameters["nextStep"]: + self.StoredVariables["Analysis"].store( numpy.ravel(Xn) ) + if self._toStore("APosterioriCovariance"): + self.StoredVariables["APosterioriCovariance"].store( Pn.asfullmatrix(Xn.size) ) + covarianceXa = Pn + # Xa = Xn previousJMinimum = numpy.finfo(float).max # diff --git a/src/daComposant/daAlgorithms/UnscentedKalmanFilter.py b/src/daComposant/daAlgorithms/UnscentedKalmanFilter.py index 43c8730..e282cae 100644 --- a/src/daComposant/daAlgorithms/UnscentedKalmanFilter.py +++ b/src/daComposant/daAlgorithms/UnscentedKalmanFilter.py @@ -164,15 +164,19 @@ class ElementaryAlgorithm(BasicObjects.Algorithm): # # Initialisation # -------------- + __n = Xb.size Xn = Xb - if hasattr(B,"asfullmatrix"): Pn = B.asfullmatrix(Xn.size) + if hasattr(B,"asfullmatrix"): Pn = B.asfullmatrix(__n) else: Pn = B # - self.StoredVariables["Analysis"].store( Xn.A1 ) - if self._toStore("APosterioriCovariance"): - self.StoredVariables["APosterioriCovariance"].store( Pn ) - covarianceXa = Pn - Xa = XaMin = Xb + if len(self.StoredVariables["Analysis"])==0 or not self._parameters["nextStep"]: + self.StoredVariables["Analysis"].store( numpy.ravel(Xb) ) + if self._toStore("APosterioriCovariance"): + self.StoredVariables["APosterioriCovariance"].store( Pn ) + covarianceXa = Pn + # + Xa = Xb + XaMin = Xb previousJMinimum = numpy.finfo(float).max # for step in range(duration-1): diff --git a/src/daComposant/daCore/Aidsm.py b/src/daComposant/daCore/Aidsm.py index 190b40c..e753bc4 100644 --- a/src/daComposant/daCore/Aidsm.py +++ b/src/daComposant/daCore/Aidsm.py @@ -666,10 +666,11 @@ class Aidsm(object): # ----------------------------------------------------------- - def execute(self, Executor=None, SaveCaseInFile=None): + def execute(self, Executor=None, SaveCaseInFile=None, nextStep=False): "Lancement du calcul" self.__case.register("execute",dir(),locals(),None,True) - Operator.CM.clearCache() + self.updateAlgorithmParameters(Parameters={"nextStep":bool(nextStep)}) + if not nextStep: Operator.CM.clearCache() try: if Executor == "YACS": self.__executeYACSScheme( SaveCaseInFile ) else: self.__executePythonScheme( SaveCaseInFile ) @@ -751,7 +752,7 @@ class Aidsm(object): for k in self.__adaoObject['AlgorithmParameters'].keys(): if k == "Algorithm": continue if k in self.__StoredInputs: - raise ValueError("the key \"%s\s to be transfered for pickling will overwrite an existing one.") + raise ValueError("The key \"%s\" to be transfered for pickling will overwrite an existing one."%(k,)) if self.__adaoObject['AlgorithmParameters'].hasObserver( k ): self.__adaoObject['AlgorithmParameters'].removeObserver( k, "", True ) self.__StoredInputs[k] = self.__adaoObject['AlgorithmParameters'].pop(k, None) diff --git a/src/daComposant/daCore/BasicObjects.py b/src/daComposant/daCore/BasicObjects.py index 59a1b2b..c9f7202 100644 --- a/src/daComposant/daCore/BasicObjects.py +++ b/src/daComposant/daCore/BasicObjects.py @@ -607,6 +607,7 @@ class Algorithm(object): self._parameters = {"StoreSupplementaryCalculations":[]} self.__required_parameters = {} self.__required_inputs = {"RequiredInputValues":{"mandatory":(), "optional":()}} + self.__variable_names_not_public = {"nextStep":False} # Duplication dans AlgorithmAndParameters # self.StoredVariables = {} self.StoredVariables["APosterioriCorrelations"] = Persistence.OneMatrix(name = "APosterioriCorrelations") @@ -656,6 +657,9 @@ class Algorithm(object): # Mise a jour de self._parameters avec Parameters self.__setParameters(Parameters) # + for k, v in self.__variable_names_not_public.items(): + if k not in self._parameters: self.__setParameters( {k:v} ) + # # Corrections et complements def __test_vvalue(argument, variable, argname): if argument is None: @@ -890,6 +894,8 @@ class AlgorithmAndParameters(object): self.__P.update( {"Algorithm":self.__A} ) # self.__setAlgorithm( self.__A ) + # + self.__variable_names_not_public = {"nextStep":False} # Duplication dans Algorithm def updateParameters(self, asDict = None, @@ -1005,7 +1011,9 @@ class AlgorithmAndParameters(object): elif key in self.__P: return self.__P[key] else: - return self.__P + allvariables = self.__P + for k in self.__variable_names_not_public: allvariables.pop(k, None) + return allvariables def pop(self, k, d): "Necessaire pour le pickling" @@ -1052,7 +1060,10 @@ class AlgorithmAndParameters(object): return self.__algorithm.StoredVariables[ __V ].hasDataObserver() def keys(self): - return list(self.__algorithm.keys()) + list(self.__P.keys()) + __allvariables = list(self.__algorithm.keys()) + list(self.__P.keys()) + for k in self.__variable_names_not_public: + if k in __allvariables: __allvariables.remove(k) + return __allvariables def __contains__(self, key=None): "D.__contains__(k) -> True if D has a key k, else False" diff --git a/src/daComposant/daCore/Interfaces.py b/src/daComposant/daCore/Interfaces.py index 8dfc2b8..e731346 100644 --- a/src/daComposant/daCore/Interfaces.py +++ b/src/daComposant/daCore/Interfaces.py @@ -122,8 +122,9 @@ class _TUIViewer(GenericCaseViewer): if k == "Stored" and not __v: continue if k == "ColMajor" and not __v: continue if k == "InputFunctionAsMulti" and not __v: continue + if k == "nextStep" and not __v: continue if k == "AvoidRC" and __v: continue - if k == "noDetails": continue + if k == "noDetails": continue if isinstance(__v,Persistence.Persistence): __v = __v.values() if callable(__v): __text = self._missing%__v.__name__+__text if isinstance(__v,dict): @@ -393,7 +394,7 @@ class _SCDViewer(GenericCaseViewer): __text += "%s_config['From'] = '%s'\n"%(__command,__f) __text += "%s_config['Data'] = %s\n"%(__command,__v) __text = __text.replace("''","'") - elif __k in ('Stored', 'Checked', 'ColMajor', 'InputFunctionAsMulti'): + elif __k in ('Stored', 'Checked', 'ColMajor', 'InputFunctionAsMulti', 'nextStep'): if bool(__v): __text += "%s_config['%s'] = '%s'\n"%(__command,__k,int(bool(__v))) elif __k in ('AvoidRC', 'noDetails'): -- 2.39.2