rosenbrock
Sim function for Rosenbrock function. We include a @const input to the gradient, and not the function evaluation, to scale down the gradient so the Lipschitz and smoothness term is reduced.
- rosenbrock.rosenbrock_eval(H, persis_info, sim_specs, _)
Evaluates the Rosenbrock function and its gradient
- Parameters:
H (dict) – Dictionary containing input points
persis_info (dict) – Persistent state information
sim_specs (dict) – Simulation specifications
- Returns:
numpy.ndarray- Evaluated function valuesdict - Updated persis_info
- Return type:
tuple
rosenbrock.py
1"""
2Sim function for Rosenbrock function. We include a @const input to the
3gradient, and not the function evaluation, to scale down the gradient
4so the Lipschitz and smoothness term is reduced.
5"""
6
7import numpy as np
8
9__all__ = ["rosenbrock_eval"]
10
11
12def EvaluateFunction(x, component=None):
13 """
14 Evaluates the chained Rosenbrock function
15
16 Parameters
17 ----------
18 x : :class:`numpy.ndarray`
19 Input vector
20 component : int, optional
21 Index of the function component
22
23 Returns
24 -------
25 float
26 Evaluated function value
27 """
28
29 assert len(x) % 2 == 0, "Length of input vector must be even"
30
31 n = len(x) // 2
32
33 if component is None:
34 f1 = 100 * np.power(np.power(x[::2], 2) - x[1::2], 2)
35 f2 = np.power(x[::2] - np.ones(n), 2)
36 f = np.sum(f1) + np.sum(f2)
37
38 else:
39 i = component
40 x1 = x[2 * i]
41 x2 = x[2 * i + 1]
42 f = 100 * (x1**2 - x2) ** 2 + (x1 - 1) ** 2
43
44 return f.squeeze()
45
46
47def EvaluateJacobian(x, component, const):
48 """
49 Evaluates the chained Rosenbrock Jacobian
50
51 Parameters
52 ----------
53 x : :class:`numpy.ndarray`
54 Input vector
55 component : int
56 Index of the function component
57 const : float
58 Term to scale gradient by
59
60 Returns
61 -------
62 :class:`numpy.ndarray`
63 Jacobian of the function
64 """
65
66 assert len(x) % 2 == 0, print("must be even lengthed input vector")
67
68 n = len(x) // 2
69 df = np.zeros(len(x), dtype=float)
70
71 if np.isnan(component):
72 df[::2] = 400 * np.multiply(x[::2], np.power(x[::2], 2) - x[1::2]) + 2 * (x[::2] - np.ones(n))
73 df[1::2] = -200 * (np.power(x[::2], 2) - x[1::2])
74
75 else:
76 i = component
77 x1 = x[2 * i]
78 x2 = x[2 * i + 1]
79
80 df[2 * i] = 400 * x1 * (x1**2 - x2) + 2 * (x1 - 1)
81 df[2 * i + 1] = -200 * (x1**2 - x2)
82
83 return 1.0 / const * df
84
85
86def rosenbrock_eval(H, persis_info, sim_specs, _):
87 """
88 Evaluates the Rosenbrock function and its gradient
89
90 Parameters
91 ----------
92 H : dict
93 Dictionary containing input points
94 persis_info : dict
95 Persistent state information
96 sim_specs : dict
97 Simulation specifications
98
99 Returns
100 -------
101 tuple
102 - :class:`numpy.ndarray` - Evaluated function values
103 - dict - Updated `persis_info`
104 """
105
106 if "params" in persis_info:
107 const = persis_info["params"].get("const", 1000)
108 else:
109 const = 1000
110
111 batch = len(H["x"])
112 H_o = np.zeros(batch, dtype=sim_specs["out"])
113
114 for i, x in enumerate(H["x"]):
115 if "obj_component" in H.dtype.fields:
116 obj_component = H["obj_component"][i]
117 H_o["f_i"][i] = EvaluateFunction(x, obj_component)
118
119 if persis_info.get("get_grad", False):
120 H_o["gradf_i"][i] = EvaluateJacobian(x, obj_component, const)
121
122 else:
123 H_o["f"][i] = EvaluateFunction(x)
124
125 if persis_info.get("get_grad", False):
126 H_o["grad"][i] = EvaluateJacobian(x, np.nan, const)
127
128 return H_o, persis_info