Salome HOME
Documentation and models update, pst4mod
[modules/adao.git] / src / daComposant / daNumerics / Models / TwoDimensionalRosenbrockFunctionR1960.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 sys, unittest, math, numpy
24
25 # ==============================================================================
26 class TwoDimensionalRosenbrockFunctionR1960:
27     """
28     Two-dimensional spatial function of µ=(a,b):
29
30         f(x,y) = (a - x)² + b (y -x²)²
31
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.
34
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,
38         (1960)
39     """
40     def __init__(self, nx: int = 40, ny: int = 40):
41         "Définition du maillage spatial"
42         self.nx  = max(1, nx)
43         self.ny  = max(1, ny)
44         self.x   = numpy.linspace(-2, 2, self.nx, dtype=float)
45         self.y   = numpy.linspace(-1, 3, self.ny, dtype=float)
46
47     def FieldZ(self, mu ):
48         "Fonction simulation pour un paramètre donné"
49         a, b = numpy.ravel( mu )
50         #
51         x, y = numpy.meshgrid( self.x, self.y )
52         sxymu = (a - x)**2 + b * (y - x**2)**2
53         #
54         return sxymu
55
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
59         x = xy[:, 0]
60         y = xy[:, 1]
61         return numpy.array([(a - x), math.sqrt(b) * (y - x**2)])
62
63     def get_x(self):
64         "Renvoie le maillage spatial"
65         return self.x, self.y
66
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])
72         return smu
73
74     def get_random_sample_of_mu(self, ns1: int = 1, ns2: int = 1):
75         "Renvoie l'échantillonnage paramétrique aléatoire"
76         smu = []
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)
82         return smu
83
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)]]
87
88     def get_bounds_on_parameter(self):
89         "Renvoie les bornes sur le maillage paramétrique"
90         return [[0, 2], [1, 200]]
91
92     OneRealisation = FieldZ
93
94 # ==============================================================================
95 class LocalTest(unittest.TestCase):
96     @classmethod
97     def setUpClass(cls):
98         print('\nAUTODIAGNOSTIC\n==============\n')
99         print("    " + TwoDimensionalRosenbrockFunctionR1960().__doc__.strip())
100
101     def test001(self):
102         numpy.random.seed(123456789)
103         Equation = TwoDimensionalRosenbrockFunctionR1960()
104         optimum = Equation.ValueZ( [1, 1] )
105         self.assertTrue( max(optimum) <= 0.)
106
107     def tearDown(cls):
108         print("\n    Tests OK\n")
109
110 # ==============================================================================
111 if __name__ == "__main__":
112     sys.stderr = sys.stdout
113     unittest.main(verbosity=0)