/*-------------------------------------------------------------------------------------*/
/*  NOMAD - Nonsmooth Optimization by Mesh Adaptive Direct search - version 3.0.0      */
/*                                                                                     */
/*  Copyright (C) 2001-2008  Mark Abramson        - the Boeing Company, Seattle        */
/*                           Charles Audet        - Ecole Polytechnique, Montreal      */
/*                           Gilles Couture       - Ecole Polytechnique, Montreal      */
/*                           John Dennis          - Rice University, Houston           */
/*                           Sebastien Le Digabel - Ecole Polytechnique, Montreal      */
/*                                                                                     */
/*  funded in part by AFOSR and Exxon Mobil                                            */
/*                                                                                     */
/*  Author: Sebastien Le Digabel                                                       */
/*                                                                                     */
/*  Contact information:                                                               */
/*    Ecole Polytechnique de Montreal - GERAD                                          */
/*    C.P. 6079, Succ. Centre-ville, Montreal (Quebec) H3C 3A7 Canada                  */
/*    e-mail: Sebastien.Le.Digabel@gerad.ca                                            */
/*    phone : 1-514-340-6053 #6673                                                     */
/*    fax   : 1-514-340-5665                                                           */
/*                                                                                     */
/*  This program is free software: you can redistribute it and/or modify it under the  */
/*  terms of the GNU General Public License as published by the Free Software          */
/*  Foundation, either version 3 of the License, or (at your option) any later         */
/*  version.                                                                           */
/*                                                                                     */
/*  This program is distributed in the hope that it will be useful, but WITHOUT ANY    */
/*  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A    */
/*  PARTICULAR PURPOSE.  See the GNU General Public License for more details.          */
/*                                                                                     */
/*  You should have received a copy of the GNU General Public License along with this  */
/*  program. If not, see <http://www.gnu.org/licenses/>.                               */
/*                                                                                     */
/*  You can find information on the NOMAD software at www.gerad.ca/nomad               */
/*-------------------------------------------------------------------------------------*/
#ifndef __STATS__
#define __STATS__

#include <iostream>
#include "Clock.hpp"
#include "Double.hpp"

class Stats : private Uncopyable {

private:

  int           _eval;              // number of evaluations (bb_eval + bb cache hits)
  int           _sim_bb_eval;       // number of simulated bb evaluations (bb_eval + initial cache hits)
  int           _sgte_eval;         // number of surrogate evaluations
  int           _sgte_cost;         // sgte_cost sgte evaluations count as one bb evaluation
  int           _bb_eval;           // number of black-box evaluations
  int           _failed_eval;       // number of failed evaluations
  int           _cache_hits;        // number of cache hits
  int           _interrupted_eval;  // number of sequence of evaluations that have
                                    // been interrupted
  int           _iterations;        // number of iterations
  int           _poll_pts;          // number of poll points
  int           _poll_success;      // number of poll successes

  int           _spec_pts;          // number of speculative search points
  int           _spec_success;      // number of speculative search successes

  int           _LH_pts;            // number of Latin-Hypercube (LH) search points
  int           _LH_success;        // number of LH search successes

  NOMAD::Double _stat_sum;          // sum stat     (output of type _STAT_SUM_)
  NOMAD::Double _stat_avg;          // average stat (output of type _STAT_AVG_)
  int           _cnt_avg;

  int           _p1_iterations;     // iteration in MADS phase one
  int           _p1_bbe;            // black-box evaluations in phase one

  Clock         _clock;             // wall-clock time

public:

  // constructor:
  explicit Stats ( int sgte_cost = -1 );

  // destructor:
  ~Stats ( void ) {}

  // reset the stats:
  void reset ( void );

  // SET methods:
  void add_eval             ( void  ) { ++_eval;             }
  void add_sim_bb_eval      ( void  ) { ++_sim_bb_eval;      }
  void add_sgte_eval        ( void  ) { ++_sgte_eval;        }
  void add_bb_eval          ( void  ) { ++_bb_eval;          }
  void add_failed_eval      ( void  ) { ++_failed_eval;      }
  void add_cache_hit        ( void  ) { ++_cache_hits;       }
  void add_interrupted_eval ( void  ) { ++_interrupted_eval; }
  void add_iteration        ( void  ) { ++_iterations;       }
  void add_poll_success     ( void  ) { ++_poll_success;     }
  void add_spec_success     ( void  ) { ++_spec_success;     }
  void add_LH_success       ( void  ) { ++_LH_success;       }
  void add_poll_pts         ( int i ) { _poll_pts      += i; }
  void add_spec_pts         ( int i ) { _spec_pts      += i; }
  void add_LH_pts           ( int i ) { _LH_pts        += i; }
  void add_p1_iterations    ( int i ) { _p1_iterations += i; }
  void add_p1_bbe           ( int i ) { _p1_bbe        += i; }

  void update_stat_sum      ( const NOMAD::Double & );
  void update_stat_avg      ( const NOMAD::Double & );

  // GET methods:
  int get_eval        ( void ) const { return _eval;                  }
  int get_sim_bb_eval ( void ) const { return _sim_bb_eval;           }
  int get_sgte_eval   ( void ) const { return _sgte_eval;             }
  int get_real_time   ( void ) const { return _clock.get_real_time(); }
  int get_iterations  ( void ) const { return _iterations;            }
  int get_failed_eval ( void ) const { return _failed_eval;           }

  int get_bb_eval    ( void ) const {
    return ( _sgte_cost > 0 ) ? _bb_eval + _sgte_eval/_sgte_cost : _bb_eval;
  }

  NOMAD::Double get_stat_sum ( void ) const { return _stat_sum; }
  NOMAD::Double get_stat_avg ( void ) const {
    return (_cnt_avg>0) ? _stat_avg/_cnt_avg : NOMAD::Double();
  }

  // display:
  void display ( std::ostream & out , int display_degree = 1 ) const;

};

// display:
inline std::ostream & operator << ( std::ostream & out, const Stats & s ) {
  s.display(out);
  return out;
}

#endif
