X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FdaComposant%2FdaCore%2FBasicObjects.py;h=59a1b2b78068e5658b213d40cca0f841c936ce0f;hb=671c7e1161d628a4dd90aa1eae9188e02ac35835;hp=05e9943946e8c2f51b770a0692baec2e351150e1;hpb=645aebaf1aeb203ec7c72edbdaf39cb12e4fca0e;p=modules%2Fadao.git diff --git a/src/daComposant/daCore/BasicObjects.py b/src/daComposant/daCore/BasicObjects.py index 05e9943..59a1b2b 100644 --- a/src/daComposant/daCore/BasicObjects.py +++ b/src/daComposant/daCore/BasicObjects.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2008-2017 EDF R&D +# Copyright (C) 2008-2019 EDF R&D # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -22,17 +22,21 @@ """ Définit les outils généraux élémentaires. - - Ce module est destiné à être appelée par AssimilationStudy. """ __author__ = "Jean-Philippe ARGAUD" __all__ = [] -import os, sys, logging, copy +import os +import sys +import logging +import copy import numpy +from functools import partial from daCore import Persistence from daCore import PlatformInfo +from daCore import Interfaces from daCore import Templates +from daCore.Interfaces import ImportFromScript, ImportFromFile # ============================================================================== class CacheManager(object): @@ -61,7 +65,7 @@ class CacheManager(object): __alc = False __HxV = None for i in range(min(len(self.__listOPCV),self.__lenghtOR)-1,-1,-1): - if xValue.size != self.__listOPCV[i][0].size: + if not hasattr(xValue, 'size') or (xValue.size != self.__listOPCV[i][0].size): # logging.debug("CM Différence de la taille %s de X et de celle %s du point %i déjà calculé", xValue.shape,i,self.__listOPCP[i].shape) continue if numpy.linalg.norm(numpy.ravel(xValue) - self.__listOPCV[i][0]) < self.__tolerBP * self.__listOPCV[i][2]: @@ -104,19 +108,36 @@ class Operator(object): NbCallsOfCached = 0 CM = CacheManager() # - def __init__(self, fromMethod=None, fromMatrix=None, avoidingRedundancy = True): + 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 python, soit une matrice. + 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 + matrice. Arguments : - fromMethod : argument de type fonction Python - fromMatrix : argument adapté au constructeur numpy.matrix - - avoidingRedundancy : évite ou pas les calculs redondants + - 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 ) - if fromMethod is not None: - self.__Method = fromMethod + 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 + self.__Type = "Method" + elif fromMethod is not None and not self.__inputAsMF: + self.__Method = partial( MultiFonction, _sFunction=fromMethod) self.__Matrix = None self.__Type = "Method" elif fromMatrix is not None: @@ -143,95 +164,173 @@ class Operator(object): "Renvoie le type" return self.__Type - def appliedTo(self, xValue, HValue = None): + def appliedTo(self, xValue, HValue = None, argsAsSerie = False): """ - Permet de restituer le résultat de l'application de l'opérateur à un - argument xValue. Cette méthode se contente d'appliquer, son argument - devant a priori être du bon type. + Permet de restituer le résultat de l'application de l'opérateur à une + série d'arguments xValue. Cette méthode se contente d'appliquer, chaque + argument devant a priori être du bon type. Arguments : - - xValue : argument adapté pour appliquer l'opérateur + - les arguments par série sont : + - xValue : argument adapté pour appliquer l'opérateur + - HValue : valeur précalculée de l'opérateur en ce point + - argsAsSerie : indique si les arguments sont une mono ou multi-valeur """ - if HValue is not None: - HxValue = numpy.asmatrix( numpy.ravel( HValue ) ).T - if self.__AvoidRC: - Operator.CM.storeValueInX(xValue,HxValue) + if argsAsSerie: + _xValue = xValue + _HValue = HValue else: - if self.__AvoidRC: - __alreadyCalculated, __HxV = Operator.CM.wasCalculatedIn(xValue) + _xValue = (xValue,) + if HValue is not None: + _HValue = (HValue,) else: - __alreadyCalculated = False + _HValue = HValue + PlatformInfo.isIterable( _xValue, True, " in Operator.appliedTo" ) + # + if _HValue is not None: + assert len(_xValue) == len(_HValue), "Incompatible number of elements in xValue and HValue" + HxValue = [] + for i in range(len(_HValue)): + HxValue.append( numpy.asmatrix( numpy.ravel( _HValue[i] ) ).T ) + if self.__AvoidRC: + Operator.CM.storeValueInX(_xValue[i],HxValue[-1]) + else: + HxValue = [] + _xserie = [] + _hindex = [] + for i, xv in enumerate(_xValue): + if self.__AvoidRC: + __alreadyCalculated, __HxV = Operator.CM.wasCalculatedIn(xv) + else: + __alreadyCalculated = False + # + if __alreadyCalculated: + self.__addOneCacheCall() + _hv = __HxV + else: + if self.__Matrix is not None: + self.__addOneMatrixCall() + _hv = self.__Matrix * xv + else: + self.__addOneMethodCall() + _xserie.append( xv ) + _hindex.append( i ) + _hv = None + HxValue.append( _hv ) # - if __alreadyCalculated: - self.__addOneCacheCall() - HxValue = __HxV - else: - if self.__Matrix is not None: - self.__addOneMatrixCall() - HxValue = self.__Matrix * xValue + if len(_xserie)>0 and self.__Matrix is None: + if self.__extraArgs is None: + _hserie = self.__Method( _xserie ) # Calcul MF else: - self.__addOneMethodCall() - HxValue = self.__Method( xValue ) - if self.__AvoidRC: - Operator.CM.storeValueInX(xValue,HxValue) - # - return HxValue - - def appliedControledFormTo(self, paire ): + _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: + _xv = _xserie.pop(0) + _hv = _hserie.pop(0) + HxValue[i] = _hv + if self.__AvoidRC: + Operator.CM.storeValueInX(_xv,_hv) + # + if argsAsSerie: return HxValue + else: return HxValue[-1] + + def appliedControledFormTo(self, paires, argsAsSerie = False): """ - Permet de restituer le résultat de l'application de l'opérateur à une - paire (xValue, uValue). Cette méthode se contente d'appliquer, son + Permet de restituer le résultat de l'application de l'opérateur à des + paires (xValue, uValue). Cette méthode se contente d'appliquer, son argument devant a priori être du bon type. Si la uValue est None, on suppose que l'opérateur ne s'applique qu'à xValue. Arguments : - - xValue : argument X adapté pour appliquer l'opérateur - - uValue : argument U adapté pour appliquer l'opérateur + - paires : les arguments par paire sont : + - xValue : argument X adapté pour appliquer l'opérateur + - uValue : argument U adapté pour appliquer l'opérateur + - argsAsSerie : indique si l'argument est une mono ou multi-valeur """ - assert len(paire) == 2, "Incorrect number of arguments" - xValue, uValue = paire + if argsAsSerie: _xuValue = paires + else: _xuValue = (paires,) + PlatformInfo.isIterable( _xuValue, True, " in Operator.appliedControledFormTo" ) + # if self.__Matrix is not None: - self.__addOneMatrixCall() - return self.__Matrix * xValue - elif uValue is not None: - self.__addOneMethodCall() - return self.__Method( (xValue, uValue) ) + HxValue = [] + for paire in _xuValue: + _xValue, _uValue = paire + self.__addOneMatrixCall() + HxValue.append( self.__Matrix * _xValue ) else: - self.__addOneMethodCall() - return self.__Method( xValue ) + HxValue = [] + for paire in _xuValue: + _xuValue = [] + _xValue, _uValue = paire + if _uValue is not None: + _xuValue.append( paire ) + else: + _xuValue.append( _xValue ) + self.__addOneMethodCall( len(_xuValue) ) + 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] - def appliedInXTo(self, paire ): + def appliedInXTo(self, paires, argsAsSerie = False): """ - Permet de restituer le résultat de l'application de l'opérateur à un - argument xValue, sachant que l'opérateur est valable en xNominal. - Cette méthode se contente d'appliquer, son argument devant a priori - être du bon type. Si l'opérateur est linéaire car c'est une matrice, - alors il est valable en tout point nominal et il n'est pas nécessaire - d'utiliser xNominal. - Arguments : une liste contenant - - xNominal : argument permettant de donner le point où l'opérateur - est construit pour etre ensuite appliqué - - xValue : argument adapté pour appliquer l'opérateur + Permet de restituer le résultat de l'application de l'opérateur à une + série d'arguments xValue, sachant que l'opérateur est valable en + xNominal. Cette méthode se contente d'appliquer, son argument devant a + priori être du bon type. Si l'opérateur est linéaire car c'est une + matrice, alors il est valable en tout point nominal et xNominal peut + être quelconque. Il n'y a qu'une seule paire par défaut, et argsAsSerie + permet d'indiquer que l'argument est multi-paires. + Arguments : + - paires : les arguments par paire sont : + - xNominal : série d'arguments permettant de donner le point où + l'opérateur est construit pour être ensuite appliqué + - xValue : série d'arguments adaptés pour appliquer l'opérateur + - argsAsSerie : indique si l'argument est une mono ou multi-valeur """ - assert len(paire) == 2, "Incorrect number of arguments" - xNominal, xValue = paire + if argsAsSerie: _nxValue = paires + else: _nxValue = (paires,) + PlatformInfo.isIterable( _nxValue, True, " in Operator.appliedInXTo" ) + # if self.__Matrix is not None: - self.__addOneMatrixCall() - return self.__Matrix * xValue + HxValue = [] + for paire in _nxValue: + _xNominal, _xValue = paire + self.__addOneMatrixCall() + HxValue.append( self.__Matrix * _xValue ) else: - self.__addOneMethodCall() - return self.__Method( (xNominal, xValue) ) + self.__addOneMethodCall( len(_nxValue) ) + 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] - def asMatrix(self, ValueForMethodForm = "UnknownVoidValue"): + def asMatrix(self, ValueForMethodForm = "UnknownVoidValue", argsAsSerie = False): """ Permet de renvoyer l'opérateur sous la forme d'une matrice """ if self.__Matrix is not None: self.__addOneMatrixCall() - return self.__Matrix + mValue = [self.__Matrix,] elif ValueForMethodForm is not "UnknownVoidValue": # Ne pas utiliser "None" - self.__addOneMethodCall() - return numpy.matrix( self.__Method( (ValueForMethodForm, None) ) ) + mValue = [] + if argsAsSerie: + self.__addOneMethodCall( len(ValueForMethodForm) ) + for _vfmf in ValueForMethodForm: + mValue.append( numpy.matrix( self.__Method(((_vfmf, None),)) ) ) + else: + self.__addOneMethodCall() + mValue = self.__Method(((ValueForMethodForm, None),)) else: raise ValueError("Matrix form of the operator defined as a function/method requires to give an operating point.") + # + if argsAsSerie: return mValue + else: return mValue[-1] def shape(self): """ @@ -265,10 +364,10 @@ class Operator(object): self.__NbCallsAsMatrix += 1 # Decompte local Operator.NbCallsAsMatrix += 1 # Decompte global - def __addOneMethodCall(self): + def __addOneMethodCall(self, nb = 1): "Comptabilise un appel" - self.__NbCallsAsMethod += 1 # Decompte local - Operator.NbCallsAsMethod += 1 # Decompte global + self.__NbCallsAsMethod += nb # Decompte local + Operator.NbCallsAsMethod += nb # Decompte global def __addOneCacheCall(self): "Comptabilise un appel" @@ -284,20 +383,23 @@ class FullOperator(object): def __init__(self, name = "GenericFullOperator", asMatrix = None, - asOneFunction = None, # Fonction - asThreeFunctions = None, # Dictionnaire de fonctions - asScript = None, + asOneFunction = None, # 1 Fonction + asThreeFunctions = None, # 3 Fonctions in a dictionary + 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): @@ -378,11 +480,12 @@ 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 if "withmpWorkers" not in __Function: __Function["withmpWorkers"] = None + if "withmfEnabled" not in __Function: __Function["withmfEnabled"] = inputAsMF from daNumerics.ApproximatedDerivatives import FDApproximation FDA = FDApproximation( Function = __Function["Direct"], @@ -394,29 +497,28 @@ class FullOperator(object): lenghtOfRedundancy = __Function["withLenghtOfRedundancy"], mpEnabled = __Function["withmpEnabled"], mpWorkers = __Function["withmpWorkers"], + mfEnabled = __Function["withmfEnabled"], ) - self.__FO["Direct"] = Operator( fromMethod = FDA.DirectOperator, avoidingRedundancy = avoidRC ) - self.__FO["Tangent"] = Operator( fromMethod = FDA.TangentOperator, avoidingRedundancy = avoidRC ) - self.__FO["Adjoint"] = Operator( fromMethod = FDA.AdjointOperator, avoidingRedundancy = avoidRC ) + 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 ) - self.__FO["Tangent"] = Operator( fromMethod = __Function["Tangent"], avoidingRedundancy = avoidRC ) - self.__FO["Adjoint"] = Operator( fromMethod = __Function["Adjoint"], avoidingRedundancy = avoidRC ) + 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 ) - self.__FO["Tangent"] = Operator( fromMatrix = __matrice, avoidingRedundancy = avoidRC ) - self.__FO["Adjoint"] = Operator( fromMatrix = __matrice.T, avoidingRedundancy = avoidRC ) + self.__FO["Direct"] = Operator( fromMatrix = __matrice, avoidingRedundancy = avoidRC, inputAsMultiFunction = inputAsMF ) + self.__FO["Tangent"] = Operator( fromMatrix = __matrice, avoidingRedundancy = avoidRC, inputAsMultiFunction = inputAsMF ) + self.__FO["Adjoint"] = Operator( fromMatrix = __matrice.T, avoidingRedundancy = avoidRC, inputAsMultiFunction = inputAsMF ) del __matrice else: - raise ValueError("Improperly defined observation operator, it requires at minima either a matrix, a Direct for approximate derivatives or a Tangent/Adjoint pair.") + raise ValueError("Improperly defined operator, it requires at minima either a matrix, a Direct for approximate derivatives or a Tangent/Adjoint pair.") # if __appliedInX is not None: self.__FO["AppliedInX"] = {} - if type(__appliedInX) is not dict: - raise ValueError("Error: observation operator defined by \"AppliedInX\" need a dictionary as argument.") for key in list(__appliedInX.keys()): if type( __appliedInX[key] ) is type( numpy.matrix([]) ): # Pour le cas où l'on a une vraie matrice @@ -459,30 +561,42 @@ class Algorithm(object): interne à l'objet, mais auquel on accède par la méthode "get". Les variables prévues sont : - - CostFunctionJ : fonction-cout globale, somme des deux parties suivantes - - CostFunctionJb : partie ébauche ou background de la fonction-cout - - CostFunctionJo : partie observations de la fonction-cout - - GradientOfCostFunctionJ : gradient de la fonction-cout globale - - GradientOfCostFunctionJb : gradient de la partie ébauche de la fonction-cout - - GradientOfCostFunctionJo : gradient de la partie observations de la fonction-cout + - APosterioriCorrelations : matrice de corrélations de la matrice A + - APosterioriCovariance : matrice de covariances a posteriori : A + - APosterioriStandardDeviations : vecteur des écart-types de la matrice A + - APosterioriVariances : vecteur des variances de la matrice A + - Analysis : vecteur d'analyse : Xa + - BMA : Background moins Analysis : Xa - Xb + - CostFunctionJ : fonction-coût globale, somme des deux parties suivantes Jb et Jo + - CostFunctionJAtCurrentOptimum : fonction-coût globale à l'état optimal courant lors d'itérations + - CostFunctionJb : partie ébauche ou background de la fonction-coût : Jb + - CostFunctionJbAtCurrentOptimum : partie ébauche à l'état optimal courant lors d'itérations + - CostFunctionJo : partie observations de la fonction-coût : Jo + - CostFunctionJoAtCurrentOptimum : partie observations à l'état optimal courant lors d'itérations + - CurrentOptimum : état optimal courant lors d'itérations - CurrentState : état courant lors d'itérations - - Analysis : l'analyse Xa - - SimulatedObservationAtBackground : l'état observé H(Xb) à l'ébauche - - SimulatedObservationAtCurrentState : l'état observé H(X) à l'état courant - - SimulatedObservationAtOptimum : l'état observé H(Xa) à l'optimum + - GradientOfCostFunctionJ : gradient de la fonction-coût globale + - GradientOfCostFunctionJb : gradient de la partie ébauche de la fonction-coût + - GradientOfCostFunctionJo : gradient de la partie observations de la fonction-coût + - IndexOfOptimum : index de l'état optimal courant lors d'itérations - Innovation : l'innovation : d = Y - H(X) - InnovationAtCurrentState : l'innovation à l'état courant : dn = Y - H(Xn) - - SigmaObs2 : indicateur de correction optimale des erreurs d'observation - - SigmaBck2 : indicateur de correction optimale des erreurs d'ébauche + - JacobianMatrixAtBackground : matrice jacobienne à l'état d'ébauche + - JacobianMatrixAtCurrentState : matrice jacobienne à l'état courant + - JacobianMatrixAtOptimum : matrice jacobienne à l'optimum + - KalmanGainAtOptimum : gain de Kalman à l'optimum - MahalanobisConsistency : indicateur de consistance des covariances - - OMA : Observation moins Analysis : Y - Xa + - OMA : Observation moins Analyse : Y - Xa - OMB : Observation moins Background : Y - Xb - - AMB : Analysis moins Background : Xa - Xb - - APosterioriCovariance : matrice A - - APosterioriVariances : variances de la matrice A - - APosterioriStandardDeviations : écart-types de la matrice A - - APosterioriCorrelations : correlations de la matrice A + - PredictedState : état prédit courant lors d'itérations - Residu : dans le cas des algorithmes de vérification + - SigmaBck2 : indicateur de correction optimale des erreurs d'ébauche + - SigmaObs2 : indicateur de correction optimale des erreurs d'observation + - SimulatedObservationAtBackground : l'état observé H(Xb) à l'ébauche + - SimulatedObservationAtCurrentOptimum : l'état observé H(X) à l'état optimal courant + - SimulatedObservationAtCurrentState : l'état observé H(X) à l'état courant + - SimulatedObservationAtOptimum : l'état observé H(Xa) à l'optimum + - SimulationQuantiles : états observés H(X) pour les quantiles demandés On peut rajouter des variables à stocker dans l'initialisation de l'algorithme élémentaire qui va hériter de cette classe """ @@ -495,37 +609,44 @@ class Algorithm(object): self.__required_inputs = {"RequiredInputValues":{"mandatory":(), "optional":()}} # self.StoredVariables = {} + self.StoredVariables["APosterioriCorrelations"] = Persistence.OneMatrix(name = "APosterioriCorrelations") + self.StoredVariables["APosterioriCovariance"] = Persistence.OneMatrix(name = "APosterioriCovariance") + self.StoredVariables["APosterioriStandardDeviations"] = Persistence.OneVector(name = "APosterioriStandardDeviations") + self.StoredVariables["APosterioriVariances"] = Persistence.OneVector(name = "APosterioriVariances") + self.StoredVariables["Analysis"] = Persistence.OneVector(name = "Analysis") + self.StoredVariables["BMA"] = Persistence.OneVector(name = "BMA") self.StoredVariables["CostFunctionJ"] = Persistence.OneScalar(name = "CostFunctionJ") - self.StoredVariables["CostFunctionJb"] = Persistence.OneScalar(name = "CostFunctionJb") - self.StoredVariables["CostFunctionJo"] = Persistence.OneScalar(name = "CostFunctionJo") self.StoredVariables["CostFunctionJAtCurrentOptimum"] = Persistence.OneScalar(name = "CostFunctionJAtCurrentOptimum") + self.StoredVariables["CostFunctionJb"] = Persistence.OneScalar(name = "CostFunctionJb") self.StoredVariables["CostFunctionJbAtCurrentOptimum"] = Persistence.OneScalar(name = "CostFunctionJbAtCurrentOptimum") + self.StoredVariables["CostFunctionJo"] = Persistence.OneScalar(name = "CostFunctionJo") self.StoredVariables["CostFunctionJoAtCurrentOptimum"] = Persistence.OneScalar(name = "CostFunctionJoAtCurrentOptimum") + self.StoredVariables["CurrentOptimum"] = Persistence.OneVector(name = "CurrentOptimum") + self.StoredVariables["CurrentState"] = Persistence.OneVector(name = "CurrentState") self.StoredVariables["GradientOfCostFunctionJ"] = Persistence.OneVector(name = "GradientOfCostFunctionJ") self.StoredVariables["GradientOfCostFunctionJb"] = Persistence.OneVector(name = "GradientOfCostFunctionJb") self.StoredVariables["GradientOfCostFunctionJo"] = Persistence.OneVector(name = "GradientOfCostFunctionJo") - self.StoredVariables["CurrentState"] = Persistence.OneVector(name = "CurrentState") - self.StoredVariables["Analysis"] = Persistence.OneVector(name = "Analysis") self.StoredVariables["IndexOfOptimum"] = Persistence.OneIndex(name = "IndexOfOptimum") - self.StoredVariables["CurrentOptimum"] = Persistence.OneVector(name = "CurrentOptimum") - self.StoredVariables["SimulatedObservationAtBackground"] = Persistence.OneVector(name = "SimulatedObservationAtBackground") - self.StoredVariables["SimulatedObservationAtCurrentState"] = Persistence.OneVector(name = "SimulatedObservationAtCurrentState") - self.StoredVariables["SimulatedObservationAtOptimum"] = Persistence.OneVector(name = "SimulatedObservationAtOptimum") - self.StoredVariables["SimulatedObservationAtCurrentOptimum"] = Persistence.OneVector(name = "SimulatedObservationAtCurrentOptimum") self.StoredVariables["Innovation"] = Persistence.OneVector(name = "Innovation") + self.StoredVariables["InnovationAtCurrentAnalysis"] = Persistence.OneVector(name = "InnovationAtCurrentAnalysis") self.StoredVariables["InnovationAtCurrentState"] = Persistence.OneVector(name = "InnovationAtCurrentState") - self.StoredVariables["SigmaObs2"] = Persistence.OneScalar(name = "SigmaObs2") - self.StoredVariables["SigmaBck2"] = Persistence.OneScalar(name = "SigmaBck2") + self.StoredVariables["JacobianMatrixAtBackground"] = Persistence.OneMatrix(name = "JacobianMatrixAtBackground") + self.StoredVariables["JacobianMatrixAtCurrentState"] = Persistence.OneMatrix(name = "JacobianMatrixAtCurrentState") + self.StoredVariables["JacobianMatrixAtOptimum"] = Persistence.OneMatrix(name = "JacobianMatrixAtOptimum") + self.StoredVariables["KalmanGainAtOptimum"] = Persistence.OneMatrix(name = "KalmanGainAtOptimum") self.StoredVariables["MahalanobisConsistency"] = Persistence.OneScalar(name = "MahalanobisConsistency") self.StoredVariables["OMA"] = Persistence.OneVector(name = "OMA") self.StoredVariables["OMB"] = Persistence.OneVector(name = "OMB") - self.StoredVariables["BMA"] = Persistence.OneVector(name = "BMA") - self.StoredVariables["APosterioriCovariance"] = Persistence.OneMatrix(name = "APosterioriCovariance") - self.StoredVariables["APosterioriVariances"] = Persistence.OneVector(name = "APosterioriVariances") - self.StoredVariables["APosterioriStandardDeviations"] = Persistence.OneVector(name = "APosterioriStandardDeviations") - self.StoredVariables["APosterioriCorrelations"] = Persistence.OneMatrix(name = "APosterioriCorrelations") - self.StoredVariables["SimulationQuantiles"] = Persistence.OneMatrix(name = "SimulationQuantiles") + self.StoredVariables["PredictedState"] = Persistence.OneVector(name = "PredictedState") self.StoredVariables["Residu"] = Persistence.OneScalar(name = "Residu") + self.StoredVariables["SigmaBck2"] = Persistence.OneScalar(name = "SigmaBck2") + self.StoredVariables["SigmaObs2"] = Persistence.OneScalar(name = "SigmaObs2") + self.StoredVariables["SimulatedObservationAtBackground"] = Persistence.OneVector(name = "SimulatedObservationAtBackground") + self.StoredVariables["SimulatedObservationAtCurrentAnalysis"]= Persistence.OneVector(name = "SimulatedObservationAtCurrentAnalysis") + self.StoredVariables["SimulatedObservationAtCurrentOptimum"] = Persistence.OneVector(name = "SimulatedObservationAtCurrentOptimum") + self.StoredVariables["SimulatedObservationAtCurrentState"] = Persistence.OneVector(name = "SimulatedObservationAtCurrentState") + self.StoredVariables["SimulatedObservationAtOptimum"] = Persistence.OneVector(name = "SimulatedObservationAtOptimum") + self.StoredVariables["SimulationQuantiles"] = Persistence.OneMatrix(name = "SimulationQuantiles") def _pre_run(self, Parameters, Xb=None, Y=None, R=None, B=None, Q=None ): "Pré-calcul" @@ -536,7 +657,7 @@ class Algorithm(object): self.__setParameters(Parameters) # # Corrections et complements - def __test_vvalue( argument, variable, argname): + def __test_vvalue(argument, variable, argname): if argument is None: if variable in self.__required_inputs["RequiredInputValues"]["mandatory"]: raise ValueError("%s %s vector %s has to be properly defined!"%(self._name,argname,variable)) @@ -546,9 +667,11 @@ class Algorithm(object): logging.debug("%s %s vector %s is not set, but is not required."%(self._name,argname,variable)) else: logging.debug("%s %s vector %s is set, and its size is %i."%(self._name,argname,variable,numpy.array(argument).size)) + return 0 __test_vvalue( Xb, "Xb", "Background or initial state" ) __test_vvalue( Y, "Y", "Observation" ) - def __test_cvalue( argument, variable, argname): + # + def __test_cvalue(argument, variable, argname): if argument is None: if variable in self.__required_inputs["RequiredInputValues"]["mandatory"]: raise ValueError("%s %s error covariance matrix %s has to be properly defined!"%(self._name,argname,variable)) @@ -558,6 +681,7 @@ class Algorithm(object): logging.debug("%s %s error covariance matrix %s is not set, but is not required."%(self._name,argname,variable)) else: logging.debug("%s %s error covariance matrix %s is set."%(self._name,argname,variable)) + return 0 __test_cvalue( R, "R", "Observation" ) __test_cvalue( B, "B", "Background" ) __test_cvalue( Q, "Q", "Evolution" ) @@ -604,6 +728,10 @@ class Algorithm(object): logging.debug("%s Terminé", self._name) return 0 + def _toStore(self, key): + "True if in StoreSupplementaryCalculations, else False" + return key in self._parameters["StoreSupplementaryCalculations"] + def get(self, key=None): """ Renvoie l'une des variables stockées identifiée par la clé, ou le @@ -729,136 +857,6 @@ class Algorithm(object): self._parameters[k] = self.setParameterValue(k) logging.debug("%s %s : %s", self._name, self.__required_parameters[k]["message"], self._parameters[k]) -# ============================================================================== -class Diagnostic(object): - """ - Classe générale d'interface de type diagnostic - - Ce template s'utilise de la manière suivante : il sert de classe "patron" en - même temps que l'une des classes de persistance, comme "OneScalar" par - exemple. - - Une classe élémentaire de diagnostic doit implémenter ses deux méthodes, la - méthode "_formula" pour écrire explicitement et proprement la formule pour - l'écriture mathématique du calcul du diagnostic (méthode interne non - publique), et "calculate" pour activer la précédente tout en ayant vérifié - et préparé les données, et pour stocker les résultats à chaque pas (méthode - externe d'activation). - """ - def __init__(self, name = "", parameters = {}): - "Initialisation" - self.name = str(name) - self.parameters = dict( parameters ) - - def _formula(self, *args): - """ - Doit implémenter l'opération élémentaire de diagnostic sous sa forme - mathématique la plus naturelle possible. - """ - raise NotImplementedError("Diagnostic mathematical formula has not been implemented!") - - def calculate(self, *args): - """ - Active la formule de calcul avec les arguments correctement rangés - """ - raise NotImplementedError("Diagnostic activation method has not been implemented!") - -# ============================================================================== -class DiagnosticAndParameters(object): - """ - Classe générale d'interface d'interface de type diagnostic - """ - def __init__(self, - name = "GenericDiagnostic", - asDiagnostic = None, - asIdentifier = None, - asDict = None, - asScript = None, - asUnit = None, - asBaseType = None, - asExistingDiags = None, - ): - """ - """ - self.__name = str(name) - self.__D = None - self.__I = None - self.__P = {} - self.__U = "" - self.__B = None - self.__E = tuple(asExistingDiags) - self.__TheDiag = None - # - if asScript is not None: - __Diag = ImportFromScript(asScript).getvalue( "Diagnostic" ) - __Iden = ImportFromScript(asScript).getvalue( "Identifier" ) - __Dict = ImportFromScript(asScript).getvalue( self.__name, "Parameters" ) - __Unit = ImportFromScript(asScript).getvalue( "Unit" ) - __Base = ImportFromScript(asScript).getvalue( "BaseType" ) - else: - __Diag = asDiagnostic - __Iden = asIdentifier - __Dict = asDict - __Unit = asUnit - __Base = asBaseType - # - if __Diag is not None: - self.__D = str(__Diag) - if __Iden is not None: - self.__I = str(__Iden) - else: - self.__I = str(__Diag) - if __Dict is not None: - self.__P.update( dict(__Dict) ) - if __Unit is None or __Unit == "None": - self.__U = "" - if __Base is None or __Base == "None": - self.__B = None - # - self.__setDiagnostic( self.__D, self.__I, self.__U, self.__B, self.__P, self.__E ) - - def get(self): - "Renvoie l'objet" - return self.__TheDiag - - def __setDiagnostic(self, __choice = None, __name = "", __unit = "", __basetype = None, __parameters = {}, __existings = () ): - """ - Permet de sélectionner un diagnostic a effectuer - """ - if __choice is None: - raise ValueError("Error: diagnostic choice has to be given") - __daDirectory = "daDiagnostics" - # - # Recherche explicitement le fichier complet - # ------------------------------------------ - __module_path = None - for directory in sys.path: - if os.path.isfile(os.path.join(directory, __daDirectory, str(__choice)+'.py')): - __module_path = os.path.abspath(os.path.join(directory, __daDirectory)) - if __module_path is None: - raise ImportError("No diagnostic module named \"%s\" was found in a \"%s\" subdirectory\n The search path is %s"%(__choice, __daDirectory, sys.path)) - # - # Importe le fichier complet comme un module - # ------------------------------------------ - try: - __sys_path_tmp = sys.path ; sys.path.insert(0,__module_path) - self.__diagnosticFile = __import__(str(__choice), globals(), locals(), []) - sys.path = __sys_path_tmp ; del __sys_path_tmp - except ImportError as e: - raise ImportError("The module named \"%s\" was found, but is incorrect at the import stage.\n The import error message is: %s"%(__choice,e)) - # - # Instancie un objet du type élémentaire du fichier - # ------------------------------------------------- - if __name in __existings: - raise ValueError("A default input with the same name \"%s\" already exists."%str(__name)) - else: - self.__TheDiag = self.__diagnosticFile.ElementaryDiagnostic( - name = __name, - unit = __unit, - basetype = __basetype, - parameters = __parameters ) - return 0 - # ============================================================================== class AlgorithmAndParameters(object): """ @@ -882,7 +880,7 @@ class AlgorithmAndParameters(object): # self.updateParameters( asDict, asScript ) # - if asScript is not None: + if asAlgorithm is None and asScript is not None: __Algo = ImportFromScript(asScript).getvalue( "Algorithm" ) else: __Algo = asAlgorithm @@ -898,7 +896,7 @@ class AlgorithmAndParameters(object): asScript = None, ): "Mise a jour des parametres" - if asScript is not None: + if asDict is None and asScript is not None: __Dict = ImportFromScript(asScript).getvalue( self.__name, "Parameters" ) else: __Dict = asDict @@ -911,7 +909,7 @@ class AlgorithmAndParameters(object): Operator.CM.clearCache() # if not isinstance(asDictAO, dict): - raise ValueError("The objects for algorithm calculation has to be given as a dictionnary, and is not") + raise ValueError("The objects for algorithm calculation have to be given together as a dictionnary, and they are not") if hasattr(asDictAO["Background"],"getO"): self.__Xb = asDictAO["Background"].getO() elif hasattr(asDictAO["CheckingPoint"],"getO"): self.__Xb = asDictAO["CheckingPoint"].getO() else: self.__Xb = None @@ -948,67 +946,55 @@ class AlgorithmAndParameters(object): def executeYACSScheme(self, FileName=None): "Permet de lancer le calcul d'assimilation" if FileName is None or not os.path.exists(FileName): - raise ValueError("a existing DIC Python file name has to be given for YACS execution.\n") - if not os.environ.has_key("ADAO_ROOT_DIR"): - raise ImportError("Unable to get ADAO_ROOT_DIR environnement variable. Please launch SALOME to add ADAO_ROOT_DIR to your environnement.\n") - # - __converterExe = os.path.join(os.environ["ADAO_ROOT_DIR"], "bin/salome", "AdaoYacsSchemaCreator.py") - __inputFile = os.path.abspath(FileName) - __outputFile = __inputFile[:__inputFile.rfind(".")] + '.xml' - # - __args = ["python", __converterExe, __inputFile, __outputFile] - import subprocess - __p = subprocess.Popen(__args) - (__stdoutdata, __stderrdata) = __p.communicate() - if not os.path.exists(__outputFile): - __msg = "An error occured during the execution of the ADAO YACS Schema\n" - __msg += "Creator applied on the input file:\n" - __msg += " %s\n"%__outputFile - __msg += "If SALOME GUI is launched by command line, see errors\n" - __msg += "details in your terminal.\n" - raise ValueError(__msg) - # + raise ValueError("a YACS file name has to be given for YACS execution.\n") + else: + __file = os.path.abspath(FileName) + logging.debug("The YACS file name is \"%s\"."%__file) + if not PlatformInfo.has_salome or \ + not PlatformInfo.has_yacs or \ + not PlatformInfo.has_adao: + raise ImportError("\n\n"+\ + "Unable to get SALOME, YACS or ADAO environnement variables.\n"+\ + "Please load the right environnement before trying to use it.\n") + # + import pilot + import SALOMERuntime + import loader + SALOMERuntime.RuntimeSALOME_setRuntime() + + r = pilot.getRuntime() + xmlLoader = loader.YACSLoader() + xmlLoader.registerProcCataLoader() try: - import pilot - import SALOMERuntime - import loader - SALOMERuntime.RuntimeSALOME_setRuntime() - - r = pilot.getRuntime() - xmlLoader = loader.YACSLoader() - xmlLoader.registerProcCataLoader() - try: - catalogAd = r.loadCatalog("proc", __outputFile) - except: - pass + catalogAd = r.loadCatalog("proc", __file) r.addCatalog(catalogAd) - - try: - p = xmlLoader.load(__outputFile) - except IOError as ex: - print("IO exception: %s"%(ex,)) - - logger = p.getLogger("parser") - if not logger.isEmpty(): - print("The imported file has errors :") - print(logger.getStr()) - - if not p.isValid(): - print("Le schéma n'est pas valide et ne peut pas être exécuté") - print(p.getErrorReport()) - - info=pilot.LinkInfo(pilot.LinkInfo.ALL_DONT_STOP) - p.checkConsistency(info) - if info.areWarningsOrErrors(): - print("Le schéma n'est pas cohérent et ne peut pas être exécuté") - print(info.getGlobalRepr()) - - e = pilot.ExecutorSwig() - e.RunW(p) - if p.getEffectiveState() != pilot.DONE: - print(p.getErrorReport()) except: - raise ValueError("execution error of YACS scheme") + pass + + try: + p = xmlLoader.load(__file) + except IOError as ex: + print("The YACS XML schema file can not be loaded: %s"%(ex,)) + + logger = p.getLogger("parser") + if not logger.isEmpty(): + print("The imported YACS XML schema has errors on parsing:") + print(logger.getStr()) + + if not p.isValid(): + print("The YACS XML schema is not valid and will not be executed:") + print(p.getErrorReport()) + + info=pilot.LinkInfo(pilot.LinkInfo.ALL_DONT_STOP) + p.checkConsistency(info) + if info.areWarningsOrErrors(): + print("The YACS XML schema is not coherent and will not be executed:") + print(info.getGlobalRepr()) + + e = pilot.ExecutorSwig() + e.RunW(p) + if p.getEffectiveState() != pilot.DONE: + print(p.getErrorReport()) # return 0 @@ -1084,8 +1070,7 @@ class AlgorithmAndParameters(object): """ Permet de sélectionner l'algorithme à utiliser pour mener à bien l'étude d'assimilation. L'argument est un champ caractère se rapportant au nom - d'un fichier contenu dans "../daAlgorithms" et réalisant l'opération - d'assimilation sur les arguments fixes. + d'un algorithme réalisant l'opération sur les arguments fixes. """ if choice is None: raise ValueError("Error: algorithm choice has to be given") @@ -1100,13 +1085,15 @@ class AlgorithmAndParameters(object): if os.path.isfile(os.path.join(directory, daDirectory, str(choice)+'.py')): module_path = os.path.abspath(os.path.join(directory, daDirectory)) if module_path is None: - raise ImportError("No algorithm module named \"%s\" was found in a \"%s\" subdirectory\n The search path is %s"%(choice, daDirectory, sys.path)) + raise ImportError("No algorithm module named \"%s\" has been found in the search path.\n The search path is %s"%(choice, sys.path)) # # Importe le fichier complet comme un module # ------------------------------------------ try: sys_path_tmp = sys.path ; sys.path.insert(0,module_path) self.__algorithmFile = __import__(str(choice), globals(), locals(), []) + if not hasattr(self.__algorithmFile, "ElementaryAlgorithm"): + raise ImportError("this module does not define a valid elementary algorithm.") self.__algorithmName = str(choice) sys.path = sys_path_tmp ; del sys_path_tmp except ImportError as e: @@ -1198,13 +1185,13 @@ class AlgorithmAndParameters(object): if not( min(__EM_shape) == max(__EM_shape) ): raise ValueError("Shape characteristic of evolution operator (EM) is incorrect: \"%s\"."%(__EM_shape,)) # - if len(self.__HO) > 0 and not(type(self.__HO) is type({})) and not( __HO_shape[1] == max(__Xb_shape) ): + if len(self.__HO) > 0 and not isinstance(self.__HO, dict) and not( __HO_shape[1] == max(__Xb_shape) ): raise ValueError("Shape characteristic of observation operator (H) \"%s\" and state (X) \"%s\" are incompatible."%(__HO_shape,__Xb_shape)) - if len(self.__HO) > 0 and not(type(self.__HO) is type({})) and not( __HO_shape[0] == max(__Y_shape) ): + if len(self.__HO) > 0 and not isinstance(self.__HO, dict) and not( __HO_shape[0] == max(__Y_shape) ): raise ValueError("Shape characteristic of observation operator (H) \"%s\" and observation (Y) \"%s\" are incompatible."%(__HO_shape,__Y_shape)) - if len(self.__HO) > 0 and not(type(self.__HO) is type({})) and len(self.__B) > 0 and not( __HO_shape[1] == __B_shape[0] ): + if len(self.__HO) > 0 and not isinstance(self.__HO, dict) and len(self.__B) > 0 and not( __HO_shape[1] == __B_shape[0] ): raise ValueError("Shape characteristic of observation operator (H) \"%s\" and a priori errors covariance matrix (B) \"%s\" are incompatible."%(__HO_shape,__B_shape)) - if len(self.__HO) > 0 and not(type(self.__HO) is type({})) and len(self.__R) > 0 and not( __HO_shape[0] == __R_shape[1] ): + if len(self.__HO) > 0 and not isinstance(self.__HO, dict) and len(self.__R) > 0 and not( __HO_shape[0] == __R_shape[1] ): raise ValueError("Shape characteristic of observation operator (H) \"%s\" and observation errors covariance matrix (R) \"%s\" are incompatible."%(__HO_shape,__R_shape)) # if self.__B is not None and len(self.__B) > 0 and not( __B_shape[1] == max(__Xb_shape) ): @@ -1220,10 +1207,10 @@ class AlgorithmAndParameters(object): if self.__R is not None and len(self.__R) > 0 and not( __R_shape[1] == max(__Y_shape) ): raise ValueError("Shape characteristic of observation errors covariance matrix (R) \"%s\" and observation (Y) \"%s\" are incompatible."%(__R_shape,__Y_shape)) # - if self.__EM is not None and len(self.__EM) > 0 and not(type(self.__EM) is type({})) and not( __EM_shape[1] == max(__Xb_shape) ): + if self.__EM is not None and len(self.__EM) > 0 and not isinstance(self.__EM, dict) and not( __EM_shape[1] == max(__Xb_shape) ): raise ValueError("Shape characteristic of evolution model (EM) \"%s\" and state (X) \"%s\" are incompatible."%(__EM_shape,__Xb_shape)) # - if self.__CM is not None and len(self.__CM) > 0 and not(type(self.__CM) is type({})) and not( __CM_shape[1] == max(__U_shape) ): + if self.__CM is not None and len(self.__CM) > 0 and not isinstance(self.__CM, dict) and not( __CM_shape[1] == max(__U_shape) ): raise ValueError("Shape characteristic of control model (CM) \"%s\" and control (U) \"%s\" are incompatible."%(__CM_shape,__U_shape)) # if ("Bounds" in self.__P) \ @@ -1234,6 +1221,45 @@ class AlgorithmAndParameters(object): # return 1 +# ============================================================================== +class RegulationAndParameters(object): + """ + Classe générale d'interface d'action pour la régulation et ses paramètres + """ + def __init__(self, + name = "GenericRegulation", + asAlgorithm = None, + asDict = None, + asScript = None, + ): + """ + """ + self.__name = str(name) + self.__P = {} + # + if asAlgorithm is None and asScript is not None: + __Algo = ImportFromScript(asScript).getvalue( "Algorithm" ) + else: + __Algo = asAlgorithm + # + if asDict is None and asScript is not None: + __Dict = ImportFromScript(asScript).getvalue( self.__name, "Parameters" ) + else: + __Dict = asDict + # + if __Dict is not None: + self.__P.update( dict(__Dict) ) + # + if __Algo is not None: + self.__P.update( {"Algorithm":__Algo} ) + + def get(self, key = None): + "Vérifie l'existence d'une clé de variable ou de paramètres" + if key in self.__P: + return self.__P[key] + else: + return self.__P + # ============================================================================== class DataObserver(object): """ @@ -1315,6 +1341,9 @@ class State(object): asVector = None, asPersistentVector = None, asScript = None, + asDataFile = None, + colNames = None, + colMajor = False, scheduledBy = None, toBeChecked = False, ): @@ -1329,6 +1358,14 @@ class State(object): nommée "name", la variable est de type "asVector" (par défaut) ou "asPersistentVector" selon que l'une de ces variables est placée à "True". + - asDataFile : si un ou plusieurs fichiers valides sont donnés + contenant des valeurs en colonnes, elles-mêmes nommées "colNames" + (s'il n'y a pas de nom de colonne indiquée, on cherche une colonne + nommée "name"), on récupère les colonnes et on les range ligne après + ligne (colMajor=False) ou colonne après colonne (colMajor=True). La + variable résultante est de type "asVector" (par défaut) ou + "asPersistentVector" selon que l'une de ces variables est placée à + "True". """ self.__name = str(name) self.__check = bool(toBeChecked) @@ -1344,6 +1381,26 @@ class State(object): __Series = ImportFromScript(asScript).getvalue( self.__name ) else: __Vector = ImportFromScript(asScript).getvalue( self.__name ) + elif asDataFile is not None: + __Vector, __Series = None, None + if asPersistentVector: + if colNames is not None: + __Series = ImportFromFile(asDataFile).getvalue( colNames )[1] + else: + __Series = ImportFromFile(asDataFile).getvalue( [self.__name,] )[1] + if bool(colMajor) and not ImportFromFile(asDataFile).getformat() == "application/numpy.npz": + __Series = numpy.transpose(__Series) + elif not bool(colMajor) and ImportFromFile(asDataFile).getformat() == "application/numpy.npz": + __Series = numpy.transpose(__Series) + else: + if colNames is not None: + __Vector = ImportFromFile(asDataFile).getvalue( colNames )[1] + else: + __Vector = ImportFromFile(asDataFile).getvalue( [self.__name,] )[1] + if bool(colMajor): + __Vector = numpy.ravel(__Vector, order = "F") + else: + __Vector = numpy.ravel(__Vector, order = "C") else: __Vector, __Series = asVector, asPersistentVector # @@ -1354,14 +1411,14 @@ class State(object): self.size = self.__V.size elif __Series is not None: self.__is_series = True - if type(__Series) in (tuple, list, numpy.ndarray, numpy.matrix): + if isinstance(__Series, (tuple, list, numpy.ndarray, numpy.matrix, str)): self.__V = Persistence.OneVector(self.__name, basetype=numpy.matrix) + if isinstance(__Series, str): __Series = eval(__Series) for member in __Series: self.__V.store( numpy.matrix( numpy.asmatrix(member).A1, numpy.float ).T ) - import sys ; sys.stdout.flush() else: self.__V = __Series - if type(self.__V.shape) in (tuple, list): + if isinstance(self.__V.shape, (tuple, list)): self.shape = self.__V.shape else: self.shape = self.__V.shape() @@ -1490,6 +1547,8 @@ class Covariance(object): def __validate(self): "Validation" + if self.__C is None: + raise UnboundLocalError("%s covariance matrix value has not been set!"%(self.__name,)) if self.ismatrix() and min(self.shape) != max(self.shape): raise ValueError("The given matrix for %s is not a square one, its shape is %s. Please check your matrix input."%(self.__name,self.shape)) if self.isobject() and min(self.shape) != max(self.shape): @@ -1656,21 +1715,16 @@ class Covariance(object): def __mul__(self, other): "x.__mul__(y) <==> x*y" - if self.ismatrix() and isinstance(other,numpy.matrix): + if self.ismatrix() and isinstance(other, (int, numpy.matrix, float)): return self.__C * other - elif self.ismatrix() and (isinstance(other,numpy.ndarray) \ - or isinstance(other,list) \ - or isinstance(other,tuple)): + elif self.ismatrix() and isinstance(other, (list, numpy.ndarray, tuple)): if numpy.ravel(other).size == self.shape[1]: # Vecteur return self.__C * numpy.asmatrix(numpy.ravel(other)).T elif numpy.asmatrix(other).shape[0] == self.shape[1]: # Matrice return self.__C * numpy.asmatrix(other) else: raise ValueError("operands could not be broadcast together with shapes %s %s in %s matrix"%(self.shape,numpy.asmatrix(other).shape,self.__name)) - elif self.isvector() and (isinstance(other,numpy.matrix) \ - or isinstance(other,numpy.ndarray) \ - or isinstance(other,list) \ - or isinstance(other,tuple)): + elif self.isvector() and isinstance(other, (list, numpy.matrix, numpy.ndarray, tuple)): if numpy.ravel(other).size == self.shape[1]: # Vecteur return numpy.asmatrix(self.__C * numpy.ravel(other)).T elif numpy.asmatrix(other).shape[0] == self.shape[1]: # Matrice @@ -1679,9 +1733,7 @@ class Covariance(object): raise ValueError("operands could not be broadcast together with shapes %s %s in %s matrix"%(self.shape,numpy.ravel(other).shape,self.__name)) elif self.isscalar() and isinstance(other,numpy.matrix): return self.__C * other - elif self.isscalar() and (isinstance(other,numpy.ndarray) \ - or isinstance(other,list) \ - or isinstance(other,tuple)): + elif self.isscalar() and isinstance(other, (list, numpy.ndarray, tuple)): if len(numpy.asarray(other).shape) == 1 or numpy.asarray(other).shape[1] == 1 or numpy.asarray(other).shape[0] == 1: return self.__C * numpy.asmatrix(numpy.ravel(other)).T else: @@ -1693,15 +1745,22 @@ class Covariance(object): def __rmul__(self, other): "x.__rmul__(y) <==> y*x" - if self.ismatrix() and isinstance(other,numpy.matrix): + if self.ismatrix() and isinstance(other, (int, numpy.matrix, float)): return other * self.__C + elif self.ismatrix() and isinstance(other, (list, numpy.ndarray, tuple)): + if numpy.ravel(other).size == self.shape[1]: # Vecteur + return numpy.asmatrix(numpy.ravel(other)) * self.__C + elif numpy.asmatrix(other).shape[0] == self.shape[1]: # Matrice + return numpy.asmatrix(other) * self.__C + else: + raise ValueError("operands could not be broadcast together with shapes %s %s in %s matrix"%(numpy.asmatrix(other).shape,self.shape,self.__name)) elif self.isvector() and isinstance(other,numpy.matrix): if numpy.ravel(other).size == self.shape[0]: # Vecteur return numpy.asmatrix(numpy.ravel(other) * self.__C) elif numpy.asmatrix(other).shape[1] == self.shape[0]: # Matrice return numpy.asmatrix(numpy.array(other) * self.__C) else: - raise ValueError("operands could not be broadcast together with shapes %s %s in %s matrix"%(self.shape,numpy.ravel(other).shape,self.__name)) + raise ValueError("operands could not be broadcast together with shapes %s %s in %s matrix"%(numpy.ravel(other).shape,self.shape,self.__name)) elif self.isscalar() and isinstance(other,numpy.matrix): return other * self.__C elif self.isobject(): @@ -1732,14 +1791,24 @@ class CaseLogger(object): """ Conservation des commandes de creation d'un cas """ - def __init__(self, __name="", __objname="case", __viewers={}, __loaders={}): + def __init__(self, __name="", __objname="case", __addViewers=None, __addLoaders=None): self.__name = str(__name) self.__objname = str(__objname) self.__logSerie = [] self.__switchoff = False - self.__viewers = self.__loaders = {"TUI":_TUIViewer} - self.__viewers.update(__viewers) - self.__loaders.update(__loaders) + self.__viewers = { + "TUI" :Interfaces._TUIViewer, + "SCD" :Interfaces._SCDViewer, + "YACS":Interfaces._YACSViewer, + } + self.__loaders = { + "TUI" :Interfaces._TUIViewer, + "COM" :Interfaces._COMViewer, + } + if __addViewers is not None: + self.__viewers.update(dict(__addViewers)) + if __addLoaders is not None: + self.__loaders.update(dict(__addLoaders)) def register(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False): "Enregistrement d'une commande individuelle" @@ -1751,161 +1820,47 @@ class CaseLogger(object): if not __switchoff: self.__switchoff = False - def dump(self, __filename=None, __format="TUI"): - "Restitution normalisée des commandes (par les *GenericCaseViewer)" + def dump(self, __filename=None, __format="TUI", __upa=""): + "Restitution normalisée des commandes" if __format in self.__viewers: __formater = self.__viewers[__format](self.__name, self.__objname, self.__logSerie) else: raise ValueError("Dumping as \"%s\" is not available"%__format) - return __formater.dump(__filename) + return __formater.dump(__filename, __upa) - def load(self, __filename=None, __format="TUI"): + def load(self, __filename=None, __content=None, __object=None, __format="TUI"): "Chargement normalisé des commandes" if __format in self.__loaders: __formater = self.__loaders[__format]() else: raise ValueError("Loading as \"%s\" is not available"%__format) - return __formater.load(__filename) + return __formater.load(__filename, __content, __object) # ============================================================================== -class GenericCaseViewer(object): - """ - Gestion des commandes de creation d'une vue de cas - """ - def __init__(self, __name="", __objname="case", __content=None): - "Initialisation et enregistrement de l'entete" - self._name = str(__name) - self._objname = str(__objname) - self._lineSerie = [] - self._switchoff = False - self._numobservers = 2 - self._content = __content - def _addLine(self, line=""): - "Ajoute un enregistrement individuel" - self._lineSerie.append(line) - def _finalize(self): - "Enregistrement du final" - pass - def _append(self): - "Transformation de commande individuelle en enregistrement" - raise NotImplementedError() - def _extract(self): - "Transformation d'enregistrement en commande individuelle" - raise NotImplementedError() - def _interpret(self): - "Interprétation d'une commande" - raise NotImplementedError() - def dump(self, __filename=None): - "Restitution normalisée des commandes" - self._finalize() - __text = "\n".join(self._lineSerie) - __text +="\n" - if __filename is not None: - __file = os.path.abspath(__filename) - fid = open(__file,"w") - fid.write(__text) - fid.close() - return __text - def load(self, __filename=None): - "Chargement normalisé des commandes" - if os.path.exists(__filename): - self._content = open(__filename, 'r').read() - __commands = self._extract(self._content) - return __commands - def execCase(self, __filename=None): - "Exécution normalisée des commandes" - if os.path.exists(__filename): - self._content = open(__filename, 'r').read() - __retcode = self._interpret(self._content) - return __retcode - -class _TUIViewer(GenericCaseViewer): +def MultiFonction( __xserie, _extraArguments = None, _sFunction = lambda x: x ): """ - Etablissement des commandes de creation d'un cas TUI + Pour une liste ordonnée de vecteurs en entrée, renvoie en sortie la liste + correspondante de valeurs de la fonction en argument """ - def __init__(self, __name="", __objname="case", __content=None): - "Initialisation et enregistrement de l'entete" - GenericCaseViewer.__init__(self, __name, __objname, __content) - self._addLine("#\n# Python script for ADAO TUI\n#") - self._addLine("from numpy import array, matrix") - self._addLine("import adaoBuilder") - self._addLine("%s = adaoBuilder.New('%s')"%(self._objname, self._name)) - if self._content is not None: - for command in self._content: - self._append(*command) - def _append(self, __command=None, __keys=None, __local=None, __pre=None, __switchoff=False): - "Transformation d'une commande individuelle en un enregistrement" - if __command is not None and __keys is not None and __local is not None: - __text = "" - if __pre is not None: - __text += "%s = "%__pre - __text += "%s.%s( "%(self._objname,str(__command)) - if "self" in __keys: __keys.remove("self") - if __command not in ("set","get") and "Concept" in __keys: __keys.remove("Concept") - for k in __keys: - __v = __local[k] - if __v is None: continue - if k == "Checked" and not __v: continue - if k == "Stored" and not __v: continue - if k == "AvoidRC" and __v: continue - if k == "noDetails": continue - numpy.set_printoptions(precision=15,threshold=1000000,linewidth=1000*15) - __text += "%s=%s, "%(k,repr(__v)) - numpy.set_printoptions(precision=8,threshold=1000,linewidth=75) - __text.rstrip(", ") - __text += ")" - self._addLine(__text) - def _extract(self, __content=""): - "Transformation un enregistrement en d'une commande individuelle" - __is_case = False - __commands = [] - __content = __content.replace("\r\n","\n") - for line in __content.split("\n"): - if "adaoBuilder" in line and "=" in line: - self._objname = line.split("=")[0].strip() - __is_case = True - if not __is_case: - continue - else: - if self._objname+".set" in line: - __commands.append( line.replace(self._objname+".","",1) ) - return __commands - def _interpret(self, __content=""): - "Interprétation d'une commande" - __content = __content.replace("\r\n","\n") - exec(__content) - return 0 - -# ============================================================================== -class ImportFromScript(object): - """ - Obtention d'une variable nommee depuis un fichier script importe - """ - def __init__(self, __filename=None): - "Verifie l'existence et importe le script" - self.__filename = __filename.rstrip(".py") - if self.__filename is None: - raise ValueError("The name of the file, containing the variable to be read, has to be specified.") - if not os.path.isfile(str(self.__filename)+".py"): - raise ValueError("The file containing the variable to be imported doesn't seem to exist. Please check the file. The given file name is:\n \"%s\""%self.__filename) - self.__scriptfile = __import__(self.__filename, globals(), locals(), []) - self.__scriptstring = open(self.__filename+".py",'r').read() - def getvalue(self, __varname=None, __synonym=None ): - "Renvoie la variable demandee" - if __varname is None: - raise ValueError("The name of the variable to be read has to be specified. Please check the content of the file and the syntax.") - if not hasattr(self.__scriptfile, __varname): - if __synonym is None: - raise ValueError("The imported script file \"%s\" doesn't contain the mandatory variable \"%s\" to be read. Please check the content of the file and the syntax."%(str(self.__filename)+".py",__varname)) - elif not hasattr(self.__scriptfile, __synonym): - raise ValueError("The imported script file \"%s\" doesn't contain the mandatory variable \"%s\" to be read. Please check the content of the file and the syntax."%(str(self.__filename)+".py",__synonym)) - else: - return getattr(self.__scriptfile, __synonym) - else: - return getattr(self.__scriptfile, __varname) - def getstring(self): - "Renvoie le script complet" - return self.__scriptstring + # Vérifications et définitions initiales + if not PlatformInfo.isIterable( __xserie ): + raise TypeError("MultiFonction not iterable unkown input type: %s"%(type(__xserie),)) + # + # Calculs effectifs + __multiHX = [] + 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 # ============================================================================== def CostFunction3D(_x, @@ -2024,4 +1979,4 @@ def CostFunction3D(_x, # ============================================================================== if __name__ == "__main__": - print('\n AUTODIAGNOSTIC \n') + print('\n AUTODIAGNOSTIC\n')