/*------------------------------------------------------------------------*/
/*       Example #1 of how to use the NOMAD library with a user function  */
/*------------------------------------------------------------------------*/
#include "Mads.hpp"
using namespace std;

/*----------------------------------------*/
/*               The problem              */
/*----------------------------------------*/
class My_Evaluator : public Evaluator {
public:
  My_Evaluator  ( const Parameters & p ) :
    Evaluator ( p , cout ) {}

  ~My_Evaluator ( void ) {}

  bool eval_x ( Eval_Point          & x          ,
		const NOMAD::Double & h_max      ,
		bool                & count_eval   ) const {
    NOMAD::Double c1 = 0.0 , c2 = 0.0;
    for ( int i = 0 ; i < 5 ; i++ ) {
      c1 += (x[i]-1).pow2();
      c2 += (x[i]+1).pow2();
    }
    x.set_bb_output  ( 0 , x[4]  ); // objective value
    x.set_bb_output  ( 1 , c1-25 ); // constraint 1
    x.set_bb_output  ( 2 , 25-c2 ); // constraint 2

    count_eval = true; // count a black-box evaluation

    return true;       // the evaluation succeeded
  }
};

/*------------------------------------------*/
/*            NOMAD main function           */
/*------------------------------------------*/
int main ( void ) {

  // display precision:
  cout.precision(DISPLAY_PRECISION_STD);

  try {

    // parameters creation:
    Parameters p ( cout );

    p.set_DIMENSION (5);             // number of variables

    vector<bb_output_type> bbot (3); // definition of
    bbot[0] = _OBJ_;                 // output types
    bbot[1] = _PB_;
    bbot[2] = _EB_;
    p.set_BB_OUTPUT_TYPE ( bbot );

    p.set_X0 ( Point ( 5 , 0.0 ) );  // starting point

    p.set_LOWER_BOUND ( Point ( 5 , -6.0 ) ); // all var. >= -6
    Point ub ( 5 );                           // x_4 and x_5 have no bounds
    ub[0] = 5.0;                              // x_1 <= 5
    ub[1] = 6.0;                              // x_2 <= 6
    ub[2] = 7.0;                              // x_3 <= 7
    p.set_UPPER_BOUND ( ub );

    p.set_MAX_BB_EVAL (100);     // the algorithm terminates after
                                 // 100 black-box evaluations

    p.set_TMP_DIR ("/tmp");      // repertory for
                                 // temporary files
    // parameters validation:
    p.check();

    // custom evaluator creation:
    My_Evaluator ev   ( p );

    // algorithm creation and execution:
    Mads         mads ( p , &ev , cout );
    mads.run();

    // algorithm display:
    if ( p.get_display_degree() > 0 ) {
      if ( p.get_display_degree() > 1 )
	cout << endl << "MADS final display:" << endl;
      cout << mads << endl;
    }
  }
  catch ( exception & e ) {
    cerr << "\nNOMAD has been interrupted (" << e.what() << ")\n\n";
    
    return 1;
  }

  return EXIT_SUCCESS;
}
