def eval_update(fun):
     val_a = fun(0.0)
     val_b = fun(1.0)
     val_trial = fun(0.6)
     f_lim = val_a.f + (wolfe_threshold * tf.abs(val_a.f))
     return self.evaluate(
         hzl.update(fun, val_a, val_b, val_trial, f_lim))
Exemple #2
0
 def eval_update(fun, p=lambda x: x):
     val_a = hzl._apply(fun, p(0.0))
     val_b = hzl._apply(fun, p(1.0))
     val_trial = hzl._apply(fun, p(0.6))
     f_lim = val_a.f + (wolfe_threshold * tf.abs(val_a.f))
     return self.evaluate(
         hzl.update(fun, val_a, val_b, val_trial, f_lim))
Exemple #3
0
    def test_update_batching(self):
        """Tests that update function works in batching mode."""
        wolfe_threshold = 1e-6
        # We build an example function with 4 batches, each for one of the
        # following cases:
        # - a) Trial point has positive slope, so works as right end point.
        # - b) Trial point has negative slope and value is not too large,
        #      so works as left end point.
        # - c) Trial point has negative slope but the value is too high,
        #      bisect is used to squeeze the interval.
        # - d) Trial point is outside of the (a, b) interval.
        x = np.array([0.0, 0.6, 1.0])
        y = np.array([[1.0, 1.2, 1.1], [1.0, 0.9, 1.2], [1.0, 1.1, 1.2],
                      [1.0, 1.1, 1.2]])
        dy = np.array([[-0.8, 0.6, 0.6], [-0.8, -0.7, 0.6], [-0.8, -0.7, 0.6],
                       [-0.8, -0.7, 0.6]])
        fun = test_function_x_y_dy(x, y, dy)

        val_a = hzl._apply(fun, tf.zeros(4))  # Values at zero.
        val_b = hzl._apply(fun, tf.ones(4))  # Values at initial step.
        val_trial = hzl._apply(fun, [0.6, 0.6, 0.6, 1.5])
        f_lim = val_a.f + (wolfe_threshold * tf.abs(val_a.f))

        expected_left = np.array([0.0, 0.6, 0.0, 0.0])
        expected_right = np.array([0.6, 1.0, 0.3, 1.0])

        result = self.evaluate(hzl.update(fun, val_a, val_b, val_trial, f_lim))
        self.assertEqual(result.num_evals, 1)  # Had to do bisect once.
        self.assertTrue(np.all(result.stopped))
        self.assertTrue(np.all(~result.failed))
        self.assertTrue(np.all(result.left.df < 0))  # Opposite slopes.
        self.assertTrue(np.all(result.right.df >= 0))
        self.assertArrayNear(result.left.x, expected_left, 1e-5)
        self.assertArrayNear(result.right.x, expected_right, 1e-5)
Exemple #4
0
 def _success_fn():
     """Action to take if the midpoint evaluation succeeded."""
     update_result = hzl.update(value_and_gradients_function, val_left,
                                val_right, val_mid, f_lim)
     return _UpdateResult(failed=update_result.failed,
                          num_evals=update_result.num_evals + 1,
                          left=update_result.left,
                          right=update_result.right)
Exemple #5
0
 def _apply_update():
   update_result = hzl.update(
       value_and_gradients_function, next_inteval.left, next_inteval.right,
       val_mid, f_lim, active=still_active)
   return HagerZhangLineSearchResult(
       converged=next_inteval.converged,
       failed=next_inteval.failed | update_result.failed,
       iterations=next_inteval.iterations + update_result.iteration,
       func_evals=next_inteval.func_evals + update_result.num_evals,
       left=update_result.left,
       right=update_result.right)
Exemple #6
0
  def test_update_simple(self):
    """Tests that update works on a single line function."""
    # Example where trial point works as new left end point.
    wolfe_threshold = 1e-6
    x = np.array([0.0, 0.6, 1.0])
    y = np.array([1.0, 0.9, 1.2])
    dy = np.array([-0.8, -0.7, 0.6])
    fun = test_function_x_y_dy(x, y, dy)

    val_a = hzl._apply(fun, 0.0)
    val_b = hzl._apply(fun, 1.0)
    val_trial = hzl._apply(fun, 0.6)
    f_lim = val_a.f + (wolfe_threshold * tf.abs(val_a.f))

    result = self.evaluate(hzl.update(fun, val_a, val_b, val_trial, f_lim))
    self.assertEqual(result.num_evals, 0)  # No extra evaluations needed.
    self.assertTrue(result.stopped)
    self.assertTrue(~result.failed)
    self.assertAlmostEqual(result.left.x, 0.6)
    self.assertAlmostEqual(result.right.x, 1.0)
    self.assertLess(result.left.df, 0)  # Opposite slopes.
    self.assertGreaterEqual(result.right.df, 0)
    def test_update_batching(self):
        """Tests that update function works in batching mode."""
        wolfe_threshold = 1e-6
        # We build an example function with 5 batches, each for one of the
        # following cases:
        # - a) Trial point has positive slope, so works as right end point.
        # - b) Trial point has negative slope and value is not too large,
        #      so works as left end point.
        # - c) Trial point has negative slope but the value is too high,
        #      bisect is used to squeeze the interval.
        # - d) Trial point is outside of the (a, b) interval.
        # - e) Left, right, and trial are all the same, and this batch member is
        #      not active.  (This is how hager_zhang._line_search_inner_bisection
        #      passes already-converged points to `update`.)
        x = np.array([0.0, 0.6, 1.0])
        y = np.array([[1.0, 1.2, 1.1], [1.0, 0.9, 1.2], [1.0, 1.1, 1.2],
                      [1.0, 1.1, 1.2], [1.0, 0.9, 1.2]])
        dy = np.array([[-0.8, 0.6, 0.6], [-0.8, -0.7, 0.6], [-0.8, -0.7, 0.6],
                       [-0.8, -0.7, 0.6], [-0.8, -0.7, 0.6]])
        fun = _test_function_x_y_dy(x, y, dy)

        val_a = fun([0.0] * 5)  # Values at zero.
        val_b = fun([1.0] * 4 + [0.0])  # Values at initial step.
        val_trial = fun([0.6, 0.6, 0.6, 1.5, 0.0])
        active = np.array([True] * 4 + [False])
        f_lim = val_a.f + (wolfe_threshold * tf.abs(val_a.f))

        expected_left = np.array([0.0, 0.6, 0.0, 0.0, 0.0])
        expected_right = np.array([0.6, 1.0, 0.3, 1.0, 0.0])

        result = self.evaluate(
            hzl.update(fun, val_a, val_b, val_trial, f_lim, active=active))
        self.assertEqual(result.num_evals, 1)  # Had to do bisect once.
        self.assertTrue(np.all(result.stopped))
        self.assertTrue(np.all(~result.failed))
        self.assertTrue(np.all(result.left.df[:-1] < 0))  # Opposite slopes.
        self.assertTrue(np.all(result.right.df[:-1] >= 0))
        self.assertArrayNear(result.left.x, expected_left, 1e-5)
        self.assertArrayNear(result.right.x, expected_right, 1e-5)