/*-------------------------------------------------------------------------------------*/
/*  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               */
/*-------------------------------------------------------------------------------------*/
#include "Mads.hpp"
using namespace std;

// display NOMAD information:
void info ( ostream & out = cout );
// for debug only:
#ifdef DEBUG
void display_cardinalities ( ostream & out );
#endif

/*------------------------------------------*/
/*            NOMAD main function           */
/*------------------------------------------*/
int main ( int argc , char ** argv ) {

  // Mads::force_quit() will be called if ctrl-c is pressed:
  signal ( SIGINT , Mads::force_quit );

  // display:
  ostream & out = cout;
  out.precision ( DISPLAY_PRECISION_STD );

  try {

    // usage:
    if ( argc < 2 ) {
      cerr << "\nusage: nomad parameters_file\n\n";
      return 1;
    }

    // parameters creation:
    Parameters p ( out     );
    p.read       ( argv[1] );

    // parameters check:
    p.check();

    // what is NOMAD:
    if ( p.get_display_degree() > 1 )
      info(out);

    // parameters display:
    if ( p.get_display_degree() > 2 )
      out << endl << "parameters:" << endl << p << endl;

    // algorithm creation and execution:
    Mads mads ( p , NULL , out );
    mads.run();

    // algorithm display:
    if ( p.get_display_degree() > 1 ) {
      if ( p.get_display_degree() > 2 )
	out << endl << "MADS final display:" << endl;
      out << mads << endl;
    }
  }
  catch ( exception & e ) {
    cerr << "\nNOMAD has been interrupted (" << e.what() << ")\n\n";
    
#ifdef DEBUG
  display_cardinalities(out);
#endif

    return 1;
  }

#ifdef DEBUG
  display_cardinalities(out);
#endif

  return EXIT_SUCCESS;
}

/*-----------------------------------------------------*/
/*  debug display of some class objects cardinalities  */
/*-----------------------------------------------------*/
#ifdef DEBUG
  void display_cardinalities ( ostream & out ) {

  // compute the appropriate display width:
  int max = ( NOMAD::Double::get_max_cardinality() > Point::get_max_cardinality() ) ?
    NOMAD::Double::get_max_cardinality() : Point::get_max_cardinality();
  if ( Set_Element<Eval_Point>::get_max_cardinality() > max )
    max = Set_Element<Eval_Point>::get_max_cardinality();
  if ( Cache_File_Point::get_max_cardinality() > max )
    max = Cache_File_Point::get_max_cardinality();
  int w = 1+int(log(static_cast<double>(max))/LOG10);
  
  // cardinalities display:
  out << "# of objects in memory:\n";
  out << "\tDouble                  : "
      << setw(w) << NOMAD::Double::get_cardinality()
      << " (max="
      << setw(w) << NOMAD::Double::get_max_cardinality() << ")" << endl;
  out << "\tPoint                   : "
      << setw(w) << Point::get_cardinality()
      << " (max="
      << setw(w) << Point::get_max_cardinality() << ")" << endl;
  out << "\tDirection               : "
      << setw(w) << Direction::get_cardinality()
      << " (max="
      << setw(w) << Direction::get_max_cardinality() << ")" << endl;
  out << "\tSet_Element<Eval_Point> : "
      << setw(w) << Set_Element<Eval_Point>::get_cardinality()
      << " (max="
      << setw(w) << Set_Element<Eval_Point>::get_max_cardinality() << ")" << endl;
  out << "\tCache_File_Point        : "
      << setw(w) << Cache_File_Point::get_cardinality()
      << " (max="
      << setw(w) << Cache_File_Point::get_max_cardinality() << ")" << endl;
  out << endl;
}
#endif

/*------------------------------------------*/
/*          display NOMAD information       */
/*------------------------------------------*/
void info ( ostream & out ) {
  out << endl
      << "NOMAD - Nonsmooth Optimization by Mesh Adaptive Direct search - version "
      << NOMAD_VERSION << "\n"
      << "\nCopyright (C) 2001-2008\n"
      << "\tMark A. Abramson     - The Boeing Company\n"
      << "\tCharles Audet        - Ecole Polytechnique de Montreal\n"
      << "\tGilles Couture       - Ecole Polytechnique de Montreal\n"
      << "\tJohn E. Dennis, Jr.  - Rice University\n"
      << "\tSebastien Le Digabel - Ecole Polytechnique de Montreal\n"
      << "\n\tfunded in part by AFOSR and Exxon Mobil"
      << endl << endl;
}
