// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2023 Google Inc. All rights reserved.
// http://ceres-solver.org/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
//   used to endorse or promote products derived from this software without
//   specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)

#include "ceres/trust_region_step_evaluator.h"

#include <algorithm>
#include <limits>

namespace ceres::internal {

TrustRegionStepEvaluator::TrustRegionStepEvaluator(
    const double initial_cost, const int max_consecutive_nonmonotonic_steps)
    : max_consecutive_nonmonotonic_steps_(max_consecutive_nonmonotonic_steps),
      minimum_cost_(initial_cost),
      current_cost_(initial_cost),
      reference_cost_(initial_cost),
      candidate_cost_(initial_cost),
      accumulated_reference_model_cost_change_(0.0),
      accumulated_candidate_model_cost_change_(0.0),
      num_consecutive_nonmonotonic_steps_(0) {}

double TrustRegionStepEvaluator::StepQuality(
    const double cost, const double model_cost_change) const {
  // If the function evaluation for this step was a failure, in which
  // case the TrustRegionMinimizer would have set the cost to
  // std::numeric_limits<double>::max(). In this case, the division by
  // model_cost_change can result in an overflow. To prevent that from
  // happening, we will deal with this case explicitly.
  if (cost >= std::numeric_limits<double>::max()) {
    return std::numeric_limits<double>::lowest();
  }

  const double relative_decrease = (current_cost_ - cost) / model_cost_change;
  const double historical_relative_decrease =
      (reference_cost_ - cost) /
      (accumulated_reference_model_cost_change_ + model_cost_change);
  return std::max(relative_decrease, historical_relative_decrease);
}

void TrustRegionStepEvaluator::StepAccepted(const double cost,
                                            const double model_cost_change) {
  // Algorithm 10.1.2 from Trust Region Methods by Conn, Gould &
  // Toint.
  //
  // Step 3a
  current_cost_ = cost;
  accumulated_candidate_model_cost_change_ += model_cost_change;
  accumulated_reference_model_cost_change_ += model_cost_change;

  // Step 3b.
  if (current_cost_ < minimum_cost_) {
    minimum_cost_ = current_cost_;
    num_consecutive_nonmonotonic_steps_ = 0;
    candidate_cost_ = current_cost_;
    accumulated_candidate_model_cost_change_ = 0.0;
  } else {
    // Step 3c.
    ++num_consecutive_nonmonotonic_steps_;
    if (current_cost_ > candidate_cost_) {
      candidate_cost_ = current_cost_;
      accumulated_candidate_model_cost_change_ = 0.0;
    }
  }

  // Step 3d.
  //
  // At this point we have made too many non-monotonic steps and
  // we are going to reset the value of the reference iterate so
  // as to force the algorithm to descend.
  //
  // Note: In the original algorithm by Toint, this step was only
  // executed if the step was non-monotonic, but that would not handle
  // the case of max_consecutive_nonmonotonic_steps = 0. The small
  // modification of doing this always handles that corner case
  // correctly.
  if (num_consecutive_nonmonotonic_steps_ ==
      max_consecutive_nonmonotonic_steps_) {
    reference_cost_ = candidate_cost_;
    accumulated_reference_model_cost_change_ =
        accumulated_candidate_model_cost_change_;
  }
}

}  // namespace ceres::internal
