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 values

  • dict - 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