// Copyright 2014 Google Inc. All Rights Reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Author: nevena@google.com (Nevena Lazic)

#include "lossmin/minimizers/parallel-boosting-with-momentum.h"

#include <math.h>
#include <functional>

#include "lossmin/minimizers/gradient-evaluator.h"
#include "third_party/eigen/Eigen/Core"

namespace lossmin {

void ParallelBoostingWithMomentum::Setup() {
  // Initialize the approximating function parameters.
  compute_and_set_learning_rates();
  alpha_ = 0.5f;
  beta_ = 1.0f - alpha_;
  phi_center_ = Weights::Zero(gradient_evaluator().NumWeights());
}

void ParallelBoostingWithMomentum::compute_and_set_learning_rates() {
  // Per-coordinate learning rates are learning_rates[j] = 1 / sparsity * Lj,
  // where sparsity is the maximum instance l0 norm and Lj is upper bound on
  // the loss curvature along coordinate j.
  float sparsity = gradient_evaluator().Sparsity();
  gradient_evaluator().PerCoordinateCurvature(&learning_rates_);
  learning_rates_ =
      (learning_rates_.array() + l2()).inverse().matrix() / sparsity;
}

void ParallelBoostingWithMomentum::SparseInnerProductGradient(
    const Weights &weights, Weights *gradient) const {
  // Eigen library recommends computations step-by-step for best perfomance
  Weights residual = gradient_evaluator().instances() * weights;
  residual -= gradient_evaluator().labels();
  *gradient = instances_transpose_ * residual;
  *gradient /= gradient_evaluator().NumExamples();
}

float ParallelBoostingWithMomentum::Loss(const Weights &weights) const {
  // Eigen library recommends computations step-by-step for best perfomance
  Weights residual = gradient_evaluator().instances() * weights;
  residual -= gradient_evaluator().labels();
  float loss =
      0.5 * residual.squaredNorm() / gradient_evaluator().NumExamples();
  if (l2() > 0.0f) loss += 0.5 * l2() * weights.squaredNorm();
  if (l1() > 0.0f) loss += l1() * weights.cwiseAbs().sum();
  return loss;
}

void ParallelBoostingWithMomentum::ConvergenceCheck(const Weights &weights,
                                                    const Weights &gradient) {
  float error_squared = 0.0f;
  for (int i = 0; i < gradient.size(); i++) {
    // for weights > 0 the gradient should be == -l1
    if (weights(i) > zero_threshold()) {
      error_squared += (gradient(i) + l1()) * (gradient(i) + l1());
    }
    // for weights < 0 the gradient should be == l1
    else if (weights(i) < -zero_threshold()) {
      error_squared += (gradient(i) - l1()) * (gradient(i) - l1());
    }
    // for weights == 0 the gradient should be between -l1 and l1
    else {
      float err = std::max(std::abs(gradient(i)) - l1(), 0.0f);
      error_squared += err * err;
    }
  }

  if (std::sqrt(error_squared) / weights.size() < convergence_threshold()) {
    set_reached_solution(true);
    set_converged(true);
  }
}

void ParallelBoostingWithMomentum::EpochUpdate(Weights *weights, int epoch,
                                               bool check_convergence) {
  // Compute the intermediate weight vector y.
  Weights y = (1.0f - alpha_) * *weights + alpha_ * phi_center_;

  // Compute the gradient of the loss wrt y.
  Weights gradient_wrt_y = Weights::Zero(y.size());
  SparseInnerProductGradient(y, &gradient_wrt_y);

  if (l2() > 0.0f) gradient_wrt_y += l2() * y;

  // Gradient step.
  *weights -= gradient_wrt_y.cwiseProduct(learning_rates_);

  // l1 shrinkage.
  if (l1() > 0.0f) {
    L1Prox(l1() * learning_rates_, weights);
  }

  // Update the approximation function.
  phi_center_ -= (1.0 - alpha_) / alpha_ * (y - *weights);
  alpha_ =
      -beta_ / 2.0 + pow(beta_ + beta_ * beta_ / 4.0, static_cast<float>(0.5));
  beta_ *= (1.0 - alpha_);

  // Compute the gradient of the objective except the l1 part and check
  // convergence
  if (check_convergence) {
    Weights gradient_wrt_weights = Weights::Zero(weights->size());
    SparseInnerProductGradient(*weights, &gradient_wrt_weights);
    if (l2() > 0.0f) {
      gradient_wrt_weights += l2() * *weights;
    }
    ConvergenceCheck(*weights, gradient_wrt_weights);
  }
}

}  // namespace lossmin
