// 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 {

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

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

float InnerProductLossFunction::ExampleLoss(
    const Weights &weights, const InstanceSet &instances,
    const LabelSet &labels, int example) const {
  float 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, float weights_scale,
    float example_scale, Weights *gradient) const {
  float inner_product = instances.innerVector(example).dot(weights);
  if (weights_scale != 1.0f) inner_product *= weights_scale;
  float inner_product_gradient =
      InnerProductExampleGradient(inner_product, labels.coeff(example, 0));
  if (example_scale != 1.0f) 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, float weights_scale,
    float example_scale,
    std::vector<std::pair<int, float>> *example_gradient) const {
  float inner_product = instances.innerVector(example).dot(weights);
  if (weights_scale != 1.0f) inner_product *= weights_scale;
  float inner_product_gradient =
      InnerProductExampleGradient(inner_product, labels.coeff(example, 0));
  if (example_scale != 1.0f) 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.
  VectorXf inner_products = instances * weights;

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

}  // namespace lossmin
