From e37c3d9de79b7be98102dbc9521d81c5f1aaec9e Mon Sep 17 00:00:00 2001 From: Jean-Philippe ARGAUD Date: Sun, 20 Jan 2019 18:32:41 +0100 Subject: [PATCH] Adding function extra arguments capabilities --- doc/en/tui.rst | 6 +-- doc/fr/tui.rst | 6 +-- src/daComposant/daCore/Aidsm.py | 11 +++- src/daComposant/daCore/BasicObjects.py | 72 ++++++++++++++++++-------- 4 files changed, 66 insertions(+), 29 deletions(-) diff --git a/doc/en/tui.rst b/doc/en/tui.rst index 77bf92b..47da0ad 100644 --- a/doc/en/tui.rst +++ b/doc/en/tui.rst @@ -333,7 +333,7 @@ The available commands are: .. index:: single: setControlModel -**setControlModel** (*Matrix, OneFunction, ThreeFunctions, Parameters, Script, Stored*) +**setControlModel** (*Matrix, OneFunction, ThreeFunctions, Parameters, Script, ExtraArgs, Stored*) This command allows to set the control operator :math:`O`, which represents an external linear input control of the evolution or observation operator. One can refer to the :ref:`section_ref_operator_control`. Its value is @@ -374,7 +374,7 @@ The available commands are: .. index:: single: setEvolutionModel -**setEvolutionModel** (*Matrix, OneFunction, ThreeFunctions, Parameters, Script, Stored*) +**setEvolutionModel** (*Matrix, OneFunction, ThreeFunctions, Parameters, Script, ExtraArgs, Stored*) This command allows to set the evolution operator :math:`M`, which describes an elementary evolution step. Its value is defined as an object of type function or of type "*Matrix*". For the function case, various functional @@ -414,7 +414,7 @@ The available commands are: .. index:: single: setObservationOperator -**setObservationOperator** (*Matrix, OneFunction, ThreeFunctions, AppliedInXb, Parameters, Script, Stored*) +**setObservationOperator** (*Matrix, OneFunction, ThreeFunctions, AppliedInXb, Parameters, Script, ExtraArgs, Stored*) This command allows to set the evolution operator :math:`H`, which transforms the input parameters :math:`\mathbf{x}` in results :math:`\mathbf{y}` that are compared to observations :math:`\mathbf{y}^o`. diff --git a/doc/fr/tui.rst b/doc/fr/tui.rst index 7255287..1334045 100644 --- a/doc/fr/tui.rst +++ b/doc/fr/tui.rst @@ -344,7 +344,7 @@ Les commandes disponibles sont les suivantes : .. index:: single: setControlModel -**setControlModel** (*Matrix, OneFunction, ThreeFunctions, Parameters, Script, Stored*) +**setControlModel** (*Matrix, OneFunction, ThreeFunctions, Parameters, Script, ExtraArgs, Stored*) Cette commande permet de définir l'opérateur de contrôle :math:`O`, qui décrit un contrôle d'entrée linéaire externe de l'opérateur d'évolution ou d'observation. On se reportera :ref:`section_ref_operator_control`. Sa @@ -386,7 +386,7 @@ Les commandes disponibles sont les suivantes : .. index:: single: setEvolutionModel -**setEvolutionModel** (*Matrix, OneFunction, ThreeFunctions, Parameters, Script, Stored*) +**setEvolutionModel** (*Matrix, OneFunction, ThreeFunctions, Parameters, Script, ExtraArgs, Stored*) Cette commande permet de définir l'opérateur d'evolution :math:`M`, qui décrit un pas élémentaire d'évolution. Sa valeur est définie comme un objet de type fonction ou de type "*Matrix*". Dans le cas d'une fonction, @@ -428,7 +428,7 @@ Les commandes disponibles sont les suivantes : .. index:: single: setObservationOperator -**setObservationOperator** (*Matrix, OneFunction, ThreeFunctions, AppliedInXb, Parameters, Script, Stored*) +**setObservationOperator** (*Matrix, OneFunction, ThreeFunctions, AppliedInXb, Parameters, Script, ExtraArgs, Stored*) Cette commande permet de définir l'opérateur d'observation :math:`H`, qui transforme les paramètres d'entrée :math:`\mathbf{x}` en résultats :math:`\mathbf{y}` qui sont à comparer aux observations diff --git a/src/daComposant/daCore/Aidsm.py b/src/daComposant/daCore/Aidsm.py index 5908abf..50cbd33 100644 --- a/src/daComposant/daCore/Aidsm.py +++ b/src/daComposant/daCore/Aidsm.py @@ -94,6 +94,7 @@ class Aidsm(object): ColNames = None, DataFile = None, DiagonalSparseMatrix = None, + ExtraArgs = None, Info = None, InputAsMF = False, Matrix = None, @@ -139,13 +140,13 @@ class Aidsm(object): elif Concept == "ObservationOperator": self.setObservationOperator( Matrix, OneFunction, ThreeFunctions, AppliedInXb, - Parameters, Script, + Parameters, Script, ExtraArgs, Stored, AvoidRC, InputAsMF, Checked ) elif Concept in ("EvolutionModel", "ControlModel"): commande = getattr(self,"set"+Concept) commande( Matrix, OneFunction, ThreeFunctions, - Parameters, Script, Scheduler, + Parameters, Script, Scheduler, ExtraArgs, Stored, AvoidRC, InputAsMF, Checked ) else: raise ValueError("the variable named '%s' is not allowed."%str(Concept)) @@ -350,6 +351,7 @@ class Aidsm(object): AppliedInXb = None, Parameters = None, Script = None, + ExtraArgs = None, Stored = False, AvoidRC = True, InputAsMF = False, @@ -365,6 +367,7 @@ class Aidsm(object): asScript = self.__with_directory(Script), asDict = Parameters, appliedInX = AppliedInXb, + extraArguments = ExtraArgs, avoidRC = AvoidRC, inputAsMF = InputAsMF, scheduledBy = None, @@ -381,6 +384,7 @@ class Aidsm(object): Parameters = None, Script = None, Scheduler = None, + ExtraArgs = None, Stored = False, AvoidRC = True, InputAsMF = False, @@ -396,6 +400,7 @@ class Aidsm(object): asScript = self.__with_directory(Script), asDict = Parameters, appliedInX = None, + extraArguments = ExtraArgs, avoidRC = AvoidRC, inputAsMF = InputAsMF, scheduledBy = Scheduler, @@ -412,6 +417,7 @@ class Aidsm(object): Parameters = None, Script = None, Scheduler = None, + ExtraArgs = None, Stored = False, AvoidRC = True, InputAsMF = False, @@ -427,6 +433,7 @@ class Aidsm(object): asScript = self.__with_directory(Script), asDict = Parameters, appliedInX = None, + extraArguments = ExtraArgs, avoidRC = AvoidRC, inputAsMF = InputAsMF, scheduledBy = Scheduler, diff --git a/src/daComposant/daCore/BasicObjects.py b/src/daComposant/daCore/BasicObjects.py index b0068a1..b5d8a31 100644 --- a/src/daComposant/daCore/BasicObjects.py +++ b/src/daComposant/daCore/BasicObjects.py @@ -108,7 +108,13 @@ class Operator(object): NbCallsOfCached = 0 CM = CacheManager() # - def __init__(self, fromMethod=None, fromMatrix=None, avoidingRedundancy = True, inputAsMultiFunction = False): + def __init__(self, + fromMethod = None, + fromMatrix = None, + avoidingRedundancy = True, + inputAsMultiFunction = False, + extraArguments = None, + ): """ On construit un objet de ce type en fournissant, à l'aide de l'un des deux mots-clé, soit une fonction ou un multi-fonction python, soit une @@ -116,12 +122,16 @@ class Operator(object): Arguments : - fromMethod : argument de type fonction Python - fromMatrix : argument adapté au constructeur numpy.matrix - - avoidingRedundancy : évite ou pas les calculs redondants - - inputAsMultiFunction : fonction explicitement définie ou pas en multi-fonction + - avoidingRedundancy : booléen évitant (ou pas) les calculs redondants + - inputAsMultiFunction : booléen indiquant une fonction explicitement + définie (ou pas) en multi-fonction + - extraArguments : arguments supplémentaires passés à la fonction de + base et ses dérivées (tuple ou dictionnaire) """ self.__NbCallsAsMatrix, self.__NbCallsAsMethod, self.__NbCallsOfCached = 0, 0, 0 - self.__AvoidRC = bool( avoidingRedundancy ) + self.__AvoidRC = bool( avoidingRedundancy ) self.__inputAsMF = bool( inputAsMultiFunction ) + self.__extraArgs = extraArguments if fromMethod is not None and self.__inputAsMF: self.__Method = fromMethod # logtimer(fromMethod) self.__Matrix = None @@ -208,7 +218,10 @@ class Operator(object): HxValue.append( _hv ) # if len(_xserie)>0 and self.__Matrix is None: - _hserie = self.__Method( _xserie ) # Calcul MF + if self.__extraArgs is None: + _hserie = self.__Method( _xserie ) # Calcul MF + else: + _hserie = self.__Method( _xserie, self.__extraArgs ) # Calcul MF if not hasattr(_hserie, "pop"): raise TypeError("The user input multi-function doesn't seem to return sequence results, behaving like a mono-function. It has to be checked.") for i in _hindex: @@ -253,7 +266,10 @@ class Operator(object): else: _xuValue.append( _xValue ) self.__addOneMethodCall( len(_xuValue) ) - HxValue = self.__Method( _xuValue ) # Calcul MF + if self.__extraArgs is None: + HxValue = self.__Method( _xuValue ) # Calcul MF + else: + HxValue = self.__Method( _xuValue, self.__extraArgs ) # Calcul MF # if argsAsSerie: return HxValue else: return HxValue[-1] @@ -286,7 +302,10 @@ class Operator(object): HxValue.append( self.__Matrix * _xValue ) else: self.__addOneMethodCall( len(_nxValue) ) - HxValue = self.__Method( _nxValue ) # Calcul MF + if self.__extraArgs is None: + HxValue = self.__Method( _nxValue ) # Calcul MF + else: + HxValue = self.__Method( _nxValue, self.__extraArgs ) # Calcul MF # if argsAsSerie: return HxValue else: return HxValue[-1] @@ -369,16 +388,18 @@ class FullOperator(object): asScript = None, # 1 or 3 Fonction(s) by script asDict = None, # Parameters appliedInX = None, + extraArguments = None, avoidRC = True, inputAsMF = False,# Fonction(s) as Multi-Functions scheduledBy = None, toBeChecked = False, ): "" - self.__name = str(name) - self.__check = bool(toBeChecked) + self.__name = str(name) + self.__check = bool(toBeChecked) + self.__extraArgs = extraArguments # - self.__FO = {} + self.__FO = {} # __Parameters = {} if (asDict is not None) and isinstance(asDict, dict): @@ -459,7 +480,7 @@ class FullOperator(object): if "withCenteredDF" not in __Function: __Function["withCenteredDF"] = False if "withIncrement" not in __Function: __Function["withIncrement"] = 0.01 if "withdX" not in __Function: __Function["withdX"] = None - if "withAvoidingRedundancy" not in __Function: __Function["withAvoidingRedundancy"] = True + if "withAvoidingRedundancy" not in __Function: __Function["withAvoidingRedundancy"] = avoidRC if "withToleranceInRedundancy" not in __Function: __Function["withToleranceInRedundancy"] = 1.e-18 if "withLenghtOfRedundancy" not in __Function: __Function["withLenghtOfRedundancy"] = -1 if "withmpEnabled" not in __Function: __Function["withmpEnabled"] = False @@ -478,15 +499,15 @@ class FullOperator(object): mpWorkers = __Function["withmpWorkers"], mfEnabled = __Function["withmfEnabled"], ) - self.__FO["Direct"] = Operator( fromMethod = FDA.DirectOperator, avoidingRedundancy = avoidRC, inputAsMultiFunction = inputAsMF) - self.__FO["Tangent"] = Operator( fromMethod = FDA.TangentOperator, avoidingRedundancy = avoidRC, inputAsMultiFunction = inputAsMF ) - self.__FO["Adjoint"] = Operator( fromMethod = FDA.AdjointOperator, avoidingRedundancy = avoidRC, inputAsMultiFunction = inputAsMF ) + self.__FO["Direct"] = Operator( fromMethod = FDA.DirectOperator, avoidingRedundancy = avoidRC, inputAsMultiFunction = inputAsMF, extraArguments = self.__extraArgs ) + self.__FO["Tangent"] = Operator( fromMethod = FDA.TangentOperator, avoidingRedundancy = avoidRC, inputAsMultiFunction = inputAsMF, extraArguments = self.__extraArgs ) + self.__FO["Adjoint"] = Operator( fromMethod = FDA.AdjointOperator, avoidingRedundancy = avoidRC, inputAsMultiFunction = inputAsMF, extraArguments = self.__extraArgs ) elif isinstance(__Function, dict) and \ ("Direct" in __Function) and ("Tangent" in __Function) and ("Adjoint" in __Function) and \ (__Function["Direct"] is not None) and (__Function["Tangent"] is not None) and (__Function["Adjoint"] is not None): - self.__FO["Direct"] = Operator( fromMethod = __Function["Direct"], avoidingRedundancy = avoidRC, inputAsMultiFunction = inputAsMF ) - self.__FO["Tangent"] = Operator( fromMethod = __Function["Tangent"], avoidingRedundancy = avoidRC, inputAsMultiFunction = inputAsMF ) - self.__FO["Adjoint"] = Operator( fromMethod = __Function["Adjoint"], avoidingRedundancy = avoidRC, inputAsMultiFunction = inputAsMF ) + self.__FO["Direct"] = Operator( fromMethod = __Function["Direct"], avoidingRedundancy = avoidRC, inputAsMultiFunction = inputAsMF, extraArguments = self.__extraArgs ) + self.__FO["Tangent"] = Operator( fromMethod = __Function["Tangent"], avoidingRedundancy = avoidRC, inputAsMultiFunction = inputAsMF, extraArguments = self.__extraArgs ) + self.__FO["Adjoint"] = Operator( fromMethod = __Function["Adjoint"], avoidingRedundancy = avoidRC, inputAsMultiFunction = inputAsMF, extraArguments = self.__extraArgs ) elif asMatrix is not None: __matrice = numpy.matrix( __Matrix, numpy.float ) self.__FO["Direct"] = Operator( fromMatrix = __matrice, avoidingRedundancy = avoidRC, inputAsMultiFunction = inputAsMF ) @@ -1810,17 +1831,26 @@ class CaseLogger(object): return __formater.load(__filename, __content, __object) # ============================================================================== -def MultiFonction( __xserie, _sFunction = lambda x: x ): +def MultiFonction( __xserie, _extraArguments = None, _sFunction = lambda x: x ): """ Pour une liste ordonnée de vecteurs en entrée, renvoie en sortie la liste correspondante de valeurs de la fonction en argument """ if not PlatformInfo.isIterable( __xserie ): - raise ValueError("MultiFonction not iterable unkown input type: %s"%(type(__xserie),)) + raise TypeError("MultiFonction not iterable unkown input type: %s"%(type(__xserie),)) # __multiHX = [] - for __xvalue in __xserie: - __multiHX.append( _sFunction( __xvalue ) ) + if _extraArguments is None: + for __xvalue in __xserie: + __multiHX.append( _sFunction( __xvalue ) ) + elif _extraArguments is not None and isinstance(_extraArguments, (list, tuple, map)): + for __xvalue in __xserie: + __multiHX.append( _sFunction( __xvalue, *_extraArguments ) ) + elif _extraArguments is not None and isinstance(_extraArguments, dict): + for __xvalue in __xserie: + __multiHX.append( _sFunction( __xvalue, **_extraArguments ) ) + else: + raise TypeError("MultiFonction extra arguments unkown input type: %s"%(type(_extraArguments),)) # return __multiHX -- 2.39.2