// 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/losses/inner-product-loss-function.h"
#include <math.h>

namespace lossmin {

double InnerProductLossFunction::LossCurvature(
    const InstanceSet &instances) const {
  double data_curvature = (instances.cwiseProduct(instances) *
                          Weights::Ones(instances.cols())).maxCoeff();
  return curvature_ * data_curvature;
}

void InnerProductLossFunction::PerCoordinateCurvature(
    const InstanceSet &instances, VectorXd *per_coordinate_curvature) const {
  *per_coordinate_curvature =
      VectorXd::Ones(instances.rows()).transpose() *
            instances.cwiseProduct(instances) / instances.rows();
  *per_coordinate_curvature *= curvature_;
}

double InnerProductLossFunction::ExampleLoss(
    const Weights &weights, const InstanceSet &instances,
    const LabelSet &labels, int example) const {
  double inner_product = instances.innerVector(example).dot(weights);
  return InnerProductExampleLoss(inner_product, labels.coeff(example, 0));
}

void InnerProductLossFunction::AddExampleGradient(
    const Weights &weights, const InstanceSet &instances,
    const LabelSet &labels, int example, double weights_scale,
    double example_scale, Weights *gradient) const {
  double inner_product = instances.innerVector(example).dot(weights);
  if (weights_scale != 1.0) inner_product *= weights_scale;
  double inner_product_gradient =
      InnerProductExampleGradient(inner_product, labels.coeff(example, 0));
  if (example_scale != 1.0) inner_product_gradient *= example_scale;

  if (synchronous_update()) {
    std::lock_guard<std::mutex> lock(gradient_update_mutex_);
    for (InstanceSet::InnerIterator it(instances, example); it; ++it) {
      gradient->coeffRef(it.index()) += inner_product_gradient * it.value();
    }
  } else {
    for (InstanceSet::InnerIterator it(instances, example); it; ++it) {
      gradient->coeffRef(it.index()) += inner_product_gradient * it.value();
    }
  }
}

void InnerProductLossFunction::ExampleGradient(
    const Weights &weights, const InstanceSet &instances,
    const LabelSet &labels, int example, double weights_scale,
    double example_scale,
    std::vector<std::pair<int, double>> *example_gradient) const {
  double inner_product = instances.innerVector(example).dot(weights);
  if (weights_scale != 1.0) inner_product *= weights_scale;
  double inner_product_gradient =
      InnerProductExampleGradient(inner_product, labels.coeff(example, 0));
  if (example_scale != 1.0) inner_product_gradient *= example_scale;

  example_gradient->resize(instances.row(example).nonZeros());
  int i = 0;
  for (InstanceSet::InnerIterator it(instances, example); it; ++it) {
    example_gradient->at(i++) =
        std::make_pair(it.index(), inner_product_gradient * it.value());
  }
}

// Assigns labels to 'instances' given 'weights'.
void InnerProductLossFunction::PredictLabels(
    const Weights &weights, const InstanceSet &instances,
    LabelSet *labels) const {
  // Compute inner products.
  VectorXd inner_products = instances * weights;

  // Assign labels by calling InnerProductAssignLabel coefficientwise on
  // 'inner_products'.
  std::function<double(double)> assign_label_ptr =
      std::bind(&InnerProductLossFunction::InnerProductPredictLabel,
                this, std::placeholders::_1);
  *labels = inner_products.unaryExpr(assign_label_ptr);
}

}  // namespace lossmin
