Salome HOME
Documentation update with features and review corrections
[modules/adao.git] / src / daComposant / daAlgorithms / QuantileRegression.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2008-2024 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 import numpy
24 from daCore import BasicObjects, NumericObjects
25 from daAlgorithms.Atoms import mmqr
26
27 # ==============================================================================
28 class ElementaryAlgorithm(BasicObjects.Algorithm):
29     def __init__(self):
30         BasicObjects.Algorithm.__init__(self, "QUANTILEREGRESSION")
31         self.defineRequiredParameter(
32             name     = "Quantile",
33             default  = 0.5,
34             typecast = float,
35             message  = "Quantile pour la régression de quantile",
36             minval   = 0.,
37             maxval   = 1.,
38         )
39         self.defineRequiredParameter(
40             name     = "Minimizer",
41             default  = "MMQR",
42             typecast = str,
43             message  = "Minimiseur utilisé",
44             listval  = ["MMQR",],
45         )
46         self.defineRequiredParameter(
47             name     = "MaximumNumberOfIterations",
48             default  = 15000,
49             typecast = int,
50             message  = "Nombre maximal de pas d'optimisation",
51             minval   = 1,
52             oldname  = "MaximumNumberOfSteps",
53         )
54         self.defineRequiredParameter(
55             name     = "CostDecrementTolerance",
56             default  = 1.e-6,
57             typecast = float,
58             message  = "Maximum de variation de la fonction d'estimation lors de l'arrêt",
59         )
60         self.defineRequiredParameter(
61             name     = "StoreInternalVariables",
62             default  = False,
63             typecast = bool,
64             message  = "Stockage des variables internes ou intermédiaires du calcul",
65         )
66         self.defineRequiredParameter(
67             name     = "StoreSupplementaryCalculations",
68             default  = [],
69             typecast = tuple,
70             message  = "Liste de calculs supplémentaires à stocker et/ou effectuer",
71             listval  = [
72                 "Analysis",
73                 "BMA",
74                 "CostFunctionJ",
75                 "CostFunctionJb",
76                 "CostFunctionJo",
77                 "CurrentIterationNumber",
78                 "CurrentState",
79                 "Innovation",
80                 "OMA",
81                 "OMB",
82                 "SimulatedObservationAtBackground",
83                 "SimulatedObservationAtCurrentState",
84                 "SimulatedObservationAtOptimum",
85             ]
86         )
87         self.defineRequiredParameter(  # Pas de type
88             name     = "Bounds",
89             message  = "Liste des valeurs de bornes",
90         )
91         self.defineRequiredParameter(
92             name     = "InitializationPoint",
93             typecast = numpy.ravel,
94             message  = "État initial imposé (par défaut, c'est l'ébauche si None)",
95         )
96         self.requireInputArguments(
97             mandatory= ("Xb", "Y", "HO" ),
98         )
99         self.setAttributes(
100             tags=(
101                 "Optimization",
102                 "Risk",
103                 "Variational",
104             ),
105             features=(
106                 "LocalOptimization",
107                 "DerivativeNeeded",
108             ),
109         )
110
111     def run(self, Xb=None, Y=None, U=None, HO=None, EM=None, CM=None, R=None, B=None, Q=None, Parameters=None):
112         self._pre_run(Parameters, Xb, Y, U, HO, EM, CM, R, B, Q)
113         self._parameters["Bounds"] = NumericObjects.ForceNumericBounds( self._parameters["Bounds"] )
114         #
115         Hm = HO["Direct"].appliedTo
116
117         def CostFunction(x):
118             _X = numpy.asarray(x).reshape((-1, 1))
119             if self._parameters["StoreInternalVariables"] or \
120                     self._toStore("CurrentState"):
121                 self.StoredVariables["CurrentState"].store( _X )
122             _HX = numpy.asarray(Hm( _X )).reshape((-1, 1))
123             if self._toStore("SimulatedObservationAtCurrentState"):
124                 self.StoredVariables["SimulatedObservationAtCurrentState"].store( _HX )
125             Jb  = 0.
126             Jo  = 0.
127             J   = Jb + Jo
128             #
129             self.StoredVariables["CurrentIterationNumber"].store( len(self.StoredVariables["CostFunctionJ"]) )
130             self.StoredVariables["CostFunctionJb"].store( Jb )
131             self.StoredVariables["CostFunctionJo"].store( Jo )
132             self.StoredVariables["CostFunctionJ" ].store( J )
133             return _HX
134
135         def GradientOfCostFunction(x):
136             _X = numpy.asarray(x).reshape((-1, 1))
137             Hg = HO["Tangent"].asMatrix( _X )
138             return Hg
139         #
140         Xini = self._parameters["InitializationPoint"]
141         #
142         # Minimisation de la fonctionnelle
143         # --------------------------------
144         if self._parameters["Minimizer"] == "MMQR":
145             Minimum, J_optimal, Informations = mmqr.mmqr(
146                 func        = CostFunction,
147                 x0          = Xini,
148                 fprime      = GradientOfCostFunction,
149                 bounds      = self._parameters["Bounds"],
150                 quantile    = self._parameters["Quantile"],
151                 maxfun      = self._parameters["MaximumNumberOfIterations"],
152                 toler       = self._parameters["CostDecrementTolerance"],
153                 y           = Y,
154             )
155         else:
156             raise ValueError("Error in minimizer name: %s is unkown"%self._parameters["Minimizer"])
157         #
158         # Obtention de l'analyse
159         # ----------------------
160         Xa = Minimum
161         #
162         self.StoredVariables["Analysis"].store( Xa )
163         #
164         # Calculs et/ou stockages supplémentaires
165         # ---------------------------------------
166         if self._toStore("OMA") or \
167                 self._toStore("SimulatedObservationAtOptimum"):
168             HXa = Hm(Xa).reshape((-1, 1))
169         if self._toStore("Innovation") or \
170                 self._toStore("OMB") or \
171                 self._toStore("SimulatedObservationAtBackground"):
172             HXb = Hm(Xb).reshape((-1, 1))
173             Innovation = Y - HXb
174         if self._toStore("Innovation"):
175             self.StoredVariables["Innovation"].store( Innovation )
176         if self._toStore("OMB"):
177             self.StoredVariables["OMB"].store( Innovation )
178         if self._toStore("BMA"):
179             self.StoredVariables["BMA"].store( numpy.ravel(Xb) - numpy.ravel(Xa) )
180         if self._toStore("OMA"):
181             self.StoredVariables["OMA"].store( Y - HXa )
182         if self._toStore("SimulatedObservationAtBackground"):
183             self.StoredVariables["SimulatedObservationAtBackground"].store( HXb )
184         if self._toStore("SimulatedObservationAtOptimum"):
185             self.StoredVariables["SimulatedObservationAtOptimum"].store( HXa )
186         #
187         self._post_run(HO, EM)
188         return 0
189
190 # ==============================================================================
191 if __name__ == "__main__":
192     print("\n AUTODIAGNOSTIC\n")