Salome HOME
Minor source update for OM compatibility
[modules/adao.git] / src / daComposant / daAlgorithms / ParticleSwarmOptimization.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
25 from daAlgorithms.Atoms import ecwnpso, ecwopso, ecwapso, ecwspso, ecwpspso
26
27 # ==============================================================================
28 class ElementaryAlgorithm(BasicObjects.Algorithm):
29     def __init__(self):
30         BasicObjects.Algorithm.__init__(self, "PARTICLESWARMOPTIMIZATION")
31         self.defineRequiredParameter(
32             name     = "Variant",
33             default  = "CanonicalPSO",
34             typecast = str,
35             message  = "Variant ou formulation de la méthode",
36             listval  = [
37                 "CanonicalPSO",
38                 "OGCR",
39                 "SPSO-2011",
40                 "SPSO-2011-AIS",
41                 "SPSO-2011-SIS",
42                 "SPSO-2011-PSIS",
43             ],
44             listadv  = [
45                 "PSO",
46             ],
47         )
48         self.defineRequiredParameter(
49             name     = "MaximumNumberOfIterations",
50             default  = 50,
51             typecast = int,
52             message  = "Nombre maximal de pas d'optimisation",
53             minval   = 0,
54             oldname  = "MaximumNumberOfSteps",
55         )
56         self.defineRequiredParameter(
57             name     = "MaximumNumberOfFunctionEvaluations",
58             default  = 15000,
59             typecast = int,
60             message  = "Nombre maximal d'évaluations de la fonction",
61             minval   = -1,
62         )
63         self.defineRequiredParameter(
64             name     = "SetSeed",
65             typecast = numpy.random.seed,
66             message  = "Graine fixée pour le générateur aléatoire",
67         )
68         self.defineRequiredParameter(
69             name     = "NumberOfInsects",
70             default  = 40,
71             typecast = int,
72             message  = "Nombre d'insectes dans l'essaim",
73             minval   = -1,
74         )
75         self.defineRequiredParameter(
76             name     = "SwarmTopology",
77             default  = "FullyConnectedNeighborhood",
78             typecast = str,
79             message  = "Mode de définition du voisinage de chaque particule",
80             listval  = [
81                 "FullyConnectedNeighborhood", "FullyConnectedNeighbourhood", "gbest",
82                 "RingNeighborhoodWithRadius1", "RingNeighbourhoodWithRadius1", "lbest",
83                 "RingNeighborhoodWithRadius2", "RingNeighbourhoodWithRadius2",
84                 "AdaptativeRandomWith3Neighbors", "AdaptativeRandomWith3Neighbours", "abest",
85                 "AdaptativeRandomWith5Neighbors", "AdaptativeRandomWith5Neighbours",
86             ],
87             listadv  = [
88                 "VonNeumannNeighborhood", "VonNeumannNeighbourhood",
89             ],
90         )
91         self.defineRequiredParameter(
92             name     = "InertiaWeight",
93             default  = 0.72135,  # 1/(2*ln(2))
94             typecast = float,
95             message  = "Part de la vitesse de l'essaim qui est imposée à l'insecte, ou poids de l'inertie (entre 0 et 1)",  # noqa: E501
96             minval   = 0.,
97             maxval   = 1.,
98             oldname  = "SwarmVelocity",
99         )
100         self.defineRequiredParameter(
101             name     = "CognitiveAcceleration",
102             default  = 1.19315,  # 1/2+ln(2)
103             typecast = float,
104             message  = "Taux de rappel à la meilleure position de l'insecte précédemment connue (positif)",
105             minval   = 0.,
106         )
107         self.defineRequiredParameter(
108             name     = "SocialAcceleration",
109             default  = 1.19315,  # 1/2+ln(2)
110             typecast = float,
111             message  = "Taux de rappel au meilleur insecte du groupe local (positif)",
112             minval   = 0.,
113             oldname  = "GroupRecallRate",
114         )
115         self.defineRequiredParameter(
116             name     = "VelocityClampingFactor",
117             default  = 0.3,
118             typecast = float,
119             message  = "Facteur de réduction de l'amplitude de variation des vitesses (entre 0 et 1)",
120             minval   = 0.0001,
121             maxval   = 1.,
122         )
123         self.defineRequiredParameter(
124             name     = "QualityCriterion",
125             default  = "AugmentedWeightedLeastSquares",
126             typecast = str,
127             message  = "Critère de qualité utilisé",
128             listval  = [
129                 "AugmentedWeightedLeastSquares", "AWLS", "DA",
130                 "WeightedLeastSquares", "WLS",
131                 "LeastSquares", "LS", "L2",
132                 "AbsoluteValue", "L1",
133                 "MaximumError", "ME", "Linf",
134             ],
135         )
136         self.defineRequiredParameter(
137             name     = "StoreInternalVariables",
138             default  = False,
139             typecast = bool,
140             message  = "Stockage des variables internes ou intermédiaires du calcul",
141         )
142         self.defineRequiredParameter(
143             name     = "StoreSupplementaryCalculations",
144             default  = [],
145             typecast = tuple,
146             message  = "Liste de calculs supplémentaires à stocker et/ou effectuer",
147             listval  = [
148                 "Analysis",
149                 "BMA",
150                 "CostFunctionJ",
151                 "CostFunctionJb",
152                 "CostFunctionJo",
153                 "CurrentIterationNumber",
154                 "CurrentState",
155                 "Innovation",
156                 "InternalCostFunctionJ",
157                 "InternalCostFunctionJb",
158                 "InternalCostFunctionJo",
159                 "InternalStates",
160                 "OMA",
161                 "OMB",
162                 "SimulatedObservationAtBackground",
163                 "SimulatedObservationAtCurrentState",
164                 "SimulatedObservationAtOptimum",
165             ]
166         )
167         self.defineRequiredParameter(  # Pas de type
168             name     = "Bounds",
169             message  = "Liste des paires de bornes",
170         )
171         self.defineRequiredParameter(  # Pas de type
172             name     = "BoxBounds",
173             message  = "Liste des paires de bornes d'incréments",
174         )
175         self.defineRequiredParameter(
176             name     = "InitializationPoint",
177             typecast = numpy.ravel,
178             message  = "État initial imposé (par défaut, c'est l'ébauche si None)",
179         )
180         self.requireInputArguments(
181             mandatory= ("Xb", "Y", "HO", "R", "B"),
182         )
183         self.setAttributes(
184             tags=(
185                 "Optimization",
186                 "NonLinear",
187                 "MetaHeuristic",
188                 "Population",
189             ),
190             features=(
191                 "NonLocalOptimization",
192                 "DerivativeFree",
193                 "ParallelAlgorithm",
194                 "ConvergenceOnNumbers",
195             ),
196         )
197
198     def run(self, Xb=None, Y=None, U=None, HO=None, EM=None, CM=None, R=None, B=None, Q=None, Parameters=None):
199         self._pre_run(Parameters, Xb, Y, U, HO, EM, CM, R, B, Q)
200         #
201         # --------------------------
202         if self._parameters["Variant"] in ["CanonicalPSO", "PSO"]:
203             ecwnpso.ecwnpso(self, Xb, Y, HO, R, B)
204         #
205         elif self._parameters["Variant"] in ["OGCR"]:
206             ecwopso.ecwopso(self, Xb, Y, HO, R, B)
207         #
208         # Default SPSO-2011 = SPSO-2011-AIS
209         elif self._parameters["Variant"] in ["SPSO-2011", "SPSO-2011-AIS"]:
210             ecwapso.ecwapso(self, Xb, Y, HO, R, B)
211         #
212         elif self._parameters["Variant"] in ["SPSO-2011-SIS"]:
213             ecwspso.ecwspso(self, Xb, Y, HO, R, B)
214         #
215         elif self._parameters["Variant"] in ["SPSO-2011-PSIS"]:
216             ecwpspso.ecwpspso(self, Xb, Y, HO, R, B)
217         #
218         # --------------------------
219         else:
220             raise ValueError("Error in Variant name: %s"%self._parameters["Variant"])
221         #
222         self._post_run(HO, EM)
223         return 0
224
225 # ==============================================================================
226 if __name__ == "__main__":
227     print("\n AUTODIAGNOSTIC\n")