Salome HOME
Adding QuantileRegression algorithm
[modules/adao.git] / src / daComposant / daCore / BasicObjects.py
1 #-*-coding:iso-8859-1-*-
2 #
3 #  Copyright (C) 2008-2012 EDF R&D
4 #
5 #  This library is free software; you can redistribute it and/or
6 #  modify it under the terms of the GNU Lesser General Public
7 #  License as published by the Free Software Foundation; either
8 #  version 2.1 of the License.
9 #
10 #  This library is distributed in the hope that it will be useful,
11 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 #  Lesser General Public License for more details.
14 #
15 #  You should have received a copy of the GNU Lesser General Public
16 #  License along with this library; if not, write to the Free Software
17 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 #
19 #  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #
21 #  Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
22
23 __doc__ = """
24     Définit les outils généraux élémentaires.
25     
26     Ce module est destiné à etre appelée par AssimilationStudy pour constituer
27     les objets élémentaires de l'algorithme.
28 """
29 __author__ = "Jean-Philippe ARGAUD"
30
31 import numpy
32 import Persistence
33
34 # ==============================================================================
35 class Operator:
36     """
37     Classe générale d'interface de type opérateur
38     """
39     def __init__(self, fromMethod=None, fromMatrix=None):
40         """
41         On construit un objet de ce type en fournissant à l'aide de l'un des
42         deux mots-clé, soit une fonction python, soit matrice.
43         Arguments :
44         - fromMethod : argument de type fonction Python
45         - fromMatrix : argument adapté au constructeur numpy.matrix
46         """
47         if   fromMethod is not None:
48             self.__Method = fromMethod
49             self.__Matrix = None
50         elif fromMatrix is not None:
51             self.__Method = None
52             self.__Matrix = numpy.matrix( fromMatrix, numpy.float )
53         else:
54             self.__Method = None
55             self.__Matrix = None
56
57     def appliedTo(self, xValue):
58         """
59         Permet de restituer le résultat de l'application de l'opérateur à un
60         argument xValue. Cette méthode se contente d'appliquer, son argument
61         devant a priori être du bon type.
62         Arguments :
63         - xValue : argument adapté pour appliquer l'opérateur
64         """
65         if self.__Matrix is not None:
66             return self.__Matrix * xValue
67         else:
68             return self.__Method( xValue )
69
70     def appliedInXTo(self, (xNominal, xValue) ):
71         """
72         Permet de restituer le résultat de l'application de l'opérateur à un
73         argument xValue, sachant que l'opérateur est valable en xNominal.
74         Cette méthode se contente d'appliquer, son argument devant a priori
75         être du bon type. Si l'opérateur est linéaire car c'est une matrice,
76         alors il est valable en tout point nominal et il n'est pas nécessaire
77         d'utiliser xNominal.
78         Arguments : une liste contenant
79         - xNominal : argument permettant de donner le point où l'opérateur
80           est construit pour etre ensuite appliqué
81         - xValue : argument adapté pour appliquer l'opérateur
82         """
83         if self.__Matrix is not None:
84             return self.__Matrix * xValue
85         else:
86             return self.__Method( (xNominal, xValue) )
87
88     def asMatrix(self, ValueForMethodForm = None):
89         """
90         Permet de renvoyer l'opérateur sous la forme d'une matrice
91         """
92         if self.__Matrix is not None:
93             return self.__Matrix
94         elif ValueForMethodForm is not None:
95             return self.__Method( ValueForMethodForm )
96         else:
97             raise ValueError("Matrix form of the operator defined as a function/method requires to give an operating point.")
98
99     def shape(self):
100         """
101         Renvoie la taille sous forme numpy si l'opérateur est disponible sous
102         la forme d'une matrice
103         """
104         if self.__Matrix is not None:
105             return self.__Matrix.shape
106         else:
107             raise ValueError("Matrix form of the operator is not available, nor the shape")
108
109 # ==============================================================================
110 class Algorithm:
111     """
112     Classe générale d'interface de type algorithme
113     
114     Elle donne un cadre pour l'écriture d'une classe élémentaire d'algorithme
115     d'assimilation, en fournissant un container (dictionnaire) de variables
116     persistantes initialisées, et des méthodes d'accès à ces variables stockées.
117     
118     Une classe élémentaire d'algorithme doit implémenter la méthode "run".
119     """
120     def __init__(self):
121         """
122         L'initialisation présente permet de fabriquer des variables de stockage
123         disponibles de manière générique dans les algorithmes élémentaires. Ces
124         variables de stockage sont ensuite conservées dans un dictionnaire
125         interne à l'objet, mais auquel on accède par la méthode "get".
126         
127         Les variables prévues sont :
128             - CostFunctionJ  : fonction-cout globale, somme des deux parties suivantes
129             - CostFunctionJb : partie ébauche ou background de la fonction-cout
130             - CostFunctionJo : partie observations de la fonction-cout
131             - GradientOfCostFunctionJ  : gradient de la fonction-cout globale
132             - GradientOfCostFunctionJb : gradient de la partie ébauche de la fonction-cout
133             - GradientOfCostFunctionJo : gradient de la partie observations de la fonction-cout
134             - CurrentState : état courant lors d'itérations
135             - Analysis : l'analyse
136             - Innovation : l'innovation : d = Y - H Xb
137             - SigmaObs2 : correction optimale des erreurs d'observation
138             - SigmaBck2 : correction optimale des erreurs d'ébauche
139             - OMA : Observation moins Analysis : Y - Xa
140             - OMB : Observation moins Background : Y - Xb
141             - AMB : Analysis moins Background : Xa - Xb
142             - APosterioriCovariance : matrice A
143         On peut rajouter des variables à stocker dans l'initialisation de
144         l'algorithme élémentaire qui va hériter de cette classe
145         """
146         self._name = None
147         self.StoredVariables = {}
148         #
149         self.StoredVariables["CostFunctionJ"]            = Persistence.OneScalar(name = "CostFunctionJ")
150         self.StoredVariables["CostFunctionJb"]           = Persistence.OneScalar(name = "CostFunctionJb")
151         self.StoredVariables["CostFunctionJo"]           = Persistence.OneScalar(name = "CostFunctionJo")
152         self.StoredVariables["GradientOfCostFunctionJ"]  = Persistence.OneVector(name = "GradientOfCostFunctionJ")
153         self.StoredVariables["GradientOfCostFunctionJb"] = Persistence.OneVector(name = "GradientOfCostFunctionJb")
154         self.StoredVariables["GradientOfCostFunctionJo"] = Persistence.OneVector(name = "GradientOfCostFunctionJo")
155         self.StoredVariables["CurrentState"]             = Persistence.OneVector(name = "CurrentState")
156         self.StoredVariables["Analysis"]                 = Persistence.OneVector(name = "Analysis")
157         self.StoredVariables["Innovation"]               = Persistence.OneVector(name = "Innovation")
158         self.StoredVariables["SigmaObs2"]                = Persistence.OneScalar(name = "SigmaObs2")
159         self.StoredVariables["SigmaBck2"]                = Persistence.OneScalar(name = "SigmaBck2")
160         self.StoredVariables["OMA"]                      = Persistence.OneVector(name = "OMA")
161         self.StoredVariables["OMB"]                      = Persistence.OneVector(name = "OMB")
162         self.StoredVariables["BMA"]                      = Persistence.OneVector(name = "BMA")
163         self.StoredVariables["APosterioriCovariance"]    = Persistence.OneMatrix(name = "APosterioriCovariance")
164
165     def get(self, key=None):
166         """
167         Renvoie l'une des variables stockées identifiée par la clé, ou le
168         dictionnaire de l'ensemble des variables disponibles en l'absence de
169         clé. Ce sont directement les variables sous forme objet qui sont
170         renvoyées, donc les méthodes d'accès à l'objet individuel sont celles
171         des classes de persistance.
172         """
173         if key is not None:
174             return self.StoredVariables[key]
175         else:
176             return self.StoredVariables
177
178     def has_key(self, key=None):
179         """
180         Vérifie si l'une des variables stockées est identifiée par la clé.
181         """
182         return self.StoredVariables.has_key(key)
183
184     def keys(self):
185         """
186         Renvoie la liste des clés de variables stockées.
187         """
188         return self.StoredVariables.keys()
189
190     def run(self, Xb=None, Y=None, H=None, M=None, R=None, B=None, Q=None, Parameters=None):
191         """
192         Doit implémenter l'opération élémentaire de calcul d'assimilation sous
193         sa forme mathématique la plus naturelle possible.
194         """
195         raise NotImplementedError("Mathematical assimilation calculation has not been implemented!")
196
197 # ==============================================================================
198 class Diagnostic:
199     """
200     Classe générale d'interface de type diagnostic
201         
202     Ce template s'utilise de la manière suivante : il sert de classe "patron" en
203     même temps que l'une des classes de persistance, comme "OneScalar" par
204     exemple.
205     
206     Une classe élémentaire de diagnostic doit implémenter ses deux méthodes, la
207     méthode "_formula" pour écrire explicitement et proprement la formule pour
208     l'écriture mathématique du calcul du diagnostic (méthode interne non
209     publique), et "calculate" pour activer la précédente tout en ayant vérifié
210     et préparé les données, et pour stocker les résultats à chaque pas (méthode
211     externe d'activation).
212     """
213     def __init__(self, name = "", parameters = {}):
214         self.name       = str(name)
215         self.parameters = dict( parameters )
216
217     def _formula(self, *args):
218         """
219         Doit implémenter l'opération élémentaire de diagnostic sous sa forme
220         mathématique la plus naturelle possible.
221         """
222         raise NotImplementedError("Diagnostic mathematical formula has not been implemented!")
223
224     def calculate(self, *args):
225         """
226         Active la formule de calcul avec les arguments correctement rangés
227         """
228         raise NotImplementedError("Diagnostic activation method has not been implemented!")
229
230 # ==============================================================================
231 if __name__ == "__main__":
232     print '\n AUTODIAGNOSTIC \n'