// Copyright (C) 2005, 2009 International Business Machines and others.
// All Rights Reserved.
// This code is published under the Common Public License.
//
// $Id: IpSolveStatistics.cpp 1692 2010-06-21 19:10:07Z andreasw $
//
// Authors:  Andreas Waechter          IBM    2005-08-15

#include "IpSolveStatistics.hpp"
#include "IpIpoptCalculatedQuantities.hpp"
#include "IpIpoptNLP.hpp"
#include "IpIpoptData.hpp"

namespace Ipopt
{

  SolveStatistics::SolveStatistics(
    const SmartPtr<IpoptNLP>& ip_nlp,
    const SmartPtr<IpoptData>& ip_data,
    const SmartPtr<IpoptCalculatedQuantities>& ip_cq)
      :
      num_iters_(ip_data->iter_count()),
      total_cpu_time_(ip_data->TimingStats().OverallAlgorithm().TotalCpuTime()),
      total_sys_time_(ip_data->TimingStats().OverallAlgorithm().TotalSysTime()),
      total_wallclock_time_(ip_data->TimingStats().OverallAlgorithm().TotalWallclockTime()),
      num_obj_evals_(ip_nlp->f_evals()),
      num_constr_evals_(Max(ip_nlp->c_evals(), ip_nlp->d_evals())),
      num_obj_grad_evals_(ip_nlp->grad_f_evals()),
      num_constr_jac_evals_(Max(ip_nlp->jac_c_evals(),ip_nlp->jac_d_evals())),
      num_hess_evals_(ip_nlp->h_evals()),

      scaled_obj_val_(ip_cq->curr_f()),
      obj_val_(ip_cq->unscaled_curr_f()),
      scaled_dual_inf_(ip_cq->curr_dual_infeasibility(NORM_MAX)),
      dual_inf_(ip_cq->unscaled_curr_dual_infeasibility(NORM_MAX)),
      scaled_constr_viol_(ip_cq->curr_nlp_constraint_violation(NORM_MAX)),
      constr_viol_(ip_cq->unscaled_curr_nlp_constraint_violation(NORM_MAX)),
      scaled_compl_(ip_cq->curr_complementarity(0., NORM_MAX)),
      compl_(ip_cq->unscaled_curr_complementarity(0., NORM_MAX)),
      scaled_kkt_error_(ip_cq->curr_nlp_error()),
      kkt_error_(ip_cq->unscaled_curr_nlp_error())
  {}

  Index SolveStatistics::IterationCount() const
  {
    return num_iters_;
  }

  Number SolveStatistics::TotalCpuTime() const
  {
    return total_cpu_time_;
  }

  Number SolveStatistics::TotalSysTime() const
  {
    return total_sys_time_;
  }

  Number SolveStatistics::TotalWallclockTime() const
  {
    return total_wallclock_time_;
  }

  void SolveStatistics::NumberOfEvaluations(
    Index& num_obj_evals,
    Index& num_constr_evals,
    Index& num_obj_grad_evals,
    Index& num_constr_jac_evals,
    Index& num_hess_evals) const
  {
    num_obj_evals = num_obj_evals_;
    num_constr_evals = num_constr_evals_;
    num_obj_grad_evals = num_obj_grad_evals_;
    num_constr_jac_evals = num_constr_jac_evals_;
    num_hess_evals = num_hess_evals_;
  }

  void SolveStatistics::Infeasibilities(Number& dual_inf,
                                        Number& constr_viol,
                                        Number& complementarity,
                                        Number& kkt_error) const
  {
    dual_inf = dual_inf_;
    constr_viol = constr_viol_;
    complementarity = compl_;
    kkt_error = kkt_error_;
  }

  void SolveStatistics::ScaledInfeasibilities(Number& scaled_dual_inf,
      Number& scaled_constr_viol,
      Number& scaled_complementarity,
      Number& scaled_kkt_error) const
  {
    scaled_dual_inf = scaled_dual_inf_;
    scaled_constr_viol = scaled_constr_viol_;
    scaled_complementarity = scaled_compl_;
    scaled_kkt_error = scaled_kkt_error_;
  }

  Number SolveStatistics::FinalObjective() const
  {
    return obj_val_;
  }

  Number SolveStatistics::FinalScaledObjective() const
  {
    return scaled_obj_val_;
  }

} // namespace Ipopt
