1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2008-2024 EDF R&D
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.
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.
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
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
23 import sys, unittest, math, numpy
25 # ==============================================================================
26 class TwoDimensionalRosenbrockFunctionR1960:
28 Two-dimensional spatial function of µ=(a,b):
30 f(x,y) = (a - x)² + b (y -x²)²
32 with (x,y) ∈ [-2,2]x[-1,3]² and usually a=1, b=100. There is a
33 global minimum at (x,y) = (a,a²) for which f(x,y) = 0.
35 This is the non-linear non-convex parametric function of the reference:
36 Rosenbrock, H. H., An Automatic Method for Finding the Greatest or
37 Least Value of a Function, The Computer Journal, 3(3), pp.175–184,
40 def __init__(self, nx: int = 40, ny: int = 40):
41 "Définition du maillage spatial"
44 self.x = numpy.linspace(-2, 2, self.nx, dtype=float)
45 self.y = numpy.linspace(-1, 3, self.ny, dtype=float)
47 def FieldZ(self, mu ):
48 "Fonction simulation pour un paramètre donné"
49 a, b = numpy.ravel( mu )
51 x, y = numpy.meshgrid( self.x, self.y )
52 sxymu = (a - x)**2 + b * (y - x**2)**2
56 def FunctionH(self, xy, a = 1, b = 100):
57 "Construit la fonction de Rosenbrock en L2 (Scipy 1.8.1 p.1322)"
58 xy = numpy.ravel( xy ).reshape((-1, 2)) # Deux colonnes
61 return numpy.array([(a - x), math.sqrt(b) * (y - x**2)])
64 "Renvoie le maillage spatial"
67 def get_sample_of_mu(self, ns1: int = 20, ns2: int = 20):
68 "Renvoie l'échantillonnage paramétrique régulier"
69 sa = numpy.linspace(0, 2, ns1, dtype=float)
70 sb = numpy.linspace(1, 200, ns2, dtype=float)
71 smu = numpy.array([(a, b) for a in sa for b in sb])
74 def get_random_sample_of_mu(self, ns1: int = 1, ns2: int = 1):
75 "Renvoie l'échantillonnage paramétrique aléatoire"
77 for i in range(ns1 * ns2):
78 smu1 = numpy.random.uniform(0, 2)
79 smu2 = numpy.random.uniform(1, 200)
80 smu.append((smu1, smu2))
81 smu = numpy.array(smu)
84 def get_bounds_on_space(self):
85 "Renvoie les bornes sur le maillage spatial"
86 return [[min(self.x), max(self.x)], [min(self.y), max(self.y)]]
88 def get_bounds_on_parameter(self):
89 "Renvoie les bornes sur le maillage paramétrique"
90 return [[0, 2], [1, 200]]
92 OneRealisation = FieldZ
94 # ==============================================================================
95 class LocalTest(unittest.TestCase):
98 print('\nAUTODIAGNOSTIC\n==============\n')
99 print(" " + TwoDimensionalRosenbrockFunctionR1960().__doc__.strip())
102 numpy.random.seed(123456789)
103 Equation = TwoDimensionalRosenbrockFunctionR1960()
104 optimum = Equation.ValueZ( [1, 1] )
105 self.assertTrue( max(optimum) <= 0.)
108 print("\n Tests OK\n")
110 # ==============================================================================
111 if __name__ == "__main__":
112 sys.stderr = sys.stdout
113 unittest.main(verbosity=0)