Salome HOME
Documentation update with features and review corrections
[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             ),
195         )
196
197     def run(self, Xb=None, Y=None, U=None, HO=None, EM=None, CM=None, R=None, B=None, Q=None, Parameters=None):
198         self._pre_run(Parameters, Xb, Y, U, HO, EM, CM, R, B, Q)
199         #
200         # --------------------------
201         if self._parameters["Variant"] in ["CanonicalPSO", "PSO"]:
202             ecwnpso.ecwnpso(self, Xb, Y, HO, R, B)
203         #
204         elif self._parameters["Variant"] in ["OGCR"]:
205             ecwopso.ecwopso(self, Xb, Y, HO, R, B)
206         #
207         # Default SPSO-2011 = SPSO-2011-AIS
208         elif self._parameters["Variant"] in ["SPSO-2011", "SPSO-2011-AIS"]:
209             ecwapso.ecwapso(self, Xb, Y, HO, R, B)
210         #
211         elif self._parameters["Variant"] in ["SPSO-2011-SIS"]:
212             ecwspso.ecwspso(self, Xb, Y, HO, R, B)
213         #
214         elif self._parameters["Variant"] in ["SPSO-2011-PSIS"]:
215             ecwpspso.ecwpspso(self, Xb, Y, HO, R, B)
216         #
217         # --------------------------
218         else:
219             raise ValueError("Error in Variant name: %s"%self._parameters["Variant"])
220         #
221         self._post_run(HO, EM)
222         return 0
223
224 # ==============================================================================
225 if __name__ == "__main__":
226     print("\n AUTODIAGNOSTIC\n")