

#include <cassert>
#include <iostream>
using namespace std;

#include <point.h>
#include <commandline.h>

#include <print.h>
#include <random.h>

#include <exploreh.h>
#include <probparab.h>
#include <probsysequ01.h>
#include <patternsearch.h>
#include <patternsearchD2.h>
#include <explorequad.h>
#include <explorerand.h>

#include <partialderivativetest.h>
#include <lineoptimizergoldtest.h>
#include <explorelinetest.h>
// #includ <powelltest.h>
#include <explorepdtest.h>
#include <minimizecomparetest.h>
#include <exploretest.h>
#include <minexpdimtest.h>
#include <typedefs.h>


typedef point2<double> pt2;

  
void test08(int argc, char** argv)
{
  commandline cmd(argc,argv);
  double hstep(1.0);
  cmd.mapvar(hstep,"hstep");
  uint counter(200);
  cmd.mapvar(counter,"counter");


  uintc n(3);
  probparab2 fn;
  exploreh<probparab2 &,double*,double> g(fn,n,2.0,5000);

  //explorequad< exploreh<probparab2 &,double*,double> > g2(fn,n,2.0,5000);


  patternsearch< exploreh<probparab2 &,double*,double> & > pat(g,hstep);

  double x0[n] = { 0.0, 0.0, 0.0 };

  cout << "Pattern search algorithm" << endl;

  for ( pat.reset(x0); g.fn.counter<counter; )
  {
    //cout << "++pat" << endl;
    ++pat;
    cout << printvecfunc(pat.exp.xi,pat.exp.N) << endl;
    //cout << pat.xi0 << endl;
  }
  cout << printvecfunc(g.xi,n) << endl;
  cout << SHOW(g.fn.counter) << endl;
  cout << SHOW(hstep) << endl;
  cout << SHOW(pat.exp.fmin) << endl;


/*
  g.indexmax = 50;
  for (pat.reset(x0); !pat; ++pat)
    cout << g.xi[0] << " " << g.xi[1] << " " << g.xi[2]  << endl;
  cout << SHOW(fn.counter) << endl;

  cout << "The exact solution is (1,2,5)" << endl;
*/

}

void test09(int argc, char** argv)
{
  commandline cmd(argc,argv);
  double hstep(1.0);
  cmd.mapvar(hstep,"hstep");
  uint counter(200);
  cmd.mapvar(counter,"counter");
  uint average(0);
  cmd.mapvar(average,"average");
  
  uint dim=1; 
  cmd.mapvar(dim,"dim" );

  uintc n(3);
  probparab2 fn;

  typedef explorequad< exploreh<probparab2 &,double*,double> > eh2;

  eh2 g(fn,n,2.0,5000);
  patternsearchD2< eh2 & > pat(g,dim,hstep);

  double x0[n] = { 0.0, 0.0, 0.0 };

  cout << "Pattern search algorithm" << endl;

  uint k=0;
  for ( pat.reset(x0); g.fn.counter<counter; )
  {
    //cout << "++pat" << endl;
    ++pat;
    //cout << SHOW(k) << endl;
    cout << printvecfunc(pat.exp.xi,pat.exp.N) << endl;
    //cout << pat.xi0 << endl;

    ++k;
    if( (average!=0) && (k%average==0) )
    {
      cout << "average" << endl;
      for (uint j=0; j<pat.exp.N; ++j)
        pat.exp.xi[j] = (pat.xi0[0][j]+pat.xi0[1][j])*0.5;
      pat.reset();
      cout << printvecfunc(pat.exp.xi,pat.exp.N) << endl;
    }

  }
  cout << printvecfunc(g.xi,n) << endl;
  cout << SHOW(g.fn.counter) << endl;
  cout << SHOW(hstep) << endl;
  cout << SHOW(average) << endl;
  cout << SHOW(pat.exp.fmin) << endl;
}

/*
void test10(int argc, char** argv)
{
  commandline cmd(argc,argv);

  uint counter(200);
  cmd.mapvar(counter,"counter");


  uintc n(3);
  probparab2 fn;
  exploreh<probparab2 &,double*,double> g(fn,n,2.0,5000);

  double x0[n] = { 0.0, 0.0, 0.0 };

  cout << "Explore search algorithm" << endl;

  for ( g.reset(x0); g.fn.counter<counter; )
  {
    ++g;
    cout << printvecfunc(g.xi,n) << endl;
  }
  cout << printvecfunc(g.xi,n) << endl;
  cout << SHOW(g.fn.counter) << endl;
  cout << SHOW(g.fmin) << endl;
}
*/

void test11(int argc, char** argv)
{
  cout << "Testing optimizers for a 2 variable non-linear system" << endl << endl;

  commandline cmd(argc,argv);

  uint counter(200);
  cmd.mapvar(counter,"counter");

  uint dim=1; 
  cmd.mapvar(dim,"dim" );

  uintc n(2);
  double x0[n] = { 0.5, 0.5 };


  cout << "exploreh" << endl;
  exploreh<probsysequ01,double*,double> g1(n,0.2,50000);
  for ( g1.reset(x0); g1.fn.counter<counter; )
    ++g1;
  cout << printvecfunc(g1.xi,n) << endl;
  cout << SHOW(g1.fn.counter) << endl;
  cout << SHOW(g1.fmin) << endl;

  cout << "patternsearch" << endl;
  typedef exploreh<probsysequ01,double*,double> e1;
  e1 f2(n,0.2,5000);
  patternsearch< e1 & > g2(f2,0.2);

  for ( g2.reset(x0); g2.exp.fn.counter<counter; )
    ++g2;
  cout << printvecfunc(g2.exp.xi,n) << endl;
  cout << SHOW(f2.fn.counter) << endl;
  cout << SHOW(f2.fmin) << endl;

  cout << "pattern with explorequad  " <<  SHOW(dim) << endl;
  typedef explorequad< exploreh<probsysequ01,double*,double> > eh2;
  eh2 f3(n,0.2,5000);
  patternsearchD2< eh2 & > g3(f3,dim,0.2);
  for ( g3.reset(x0); f3.fn.counter<counter; )
    ++g3;
  cout << printvecfunc(g3.exp.xi,n) << endl;
  cout << SHOW(f3.fn.counter) << endl;
  cout << SHOW(f3.fmin) << endl;

  cout << "pattern  " << SHOW(dim) << endl;
  f2.fn.counter=0;
  patternsearchD2< e1 & > g4(f2,dim,0.2);
  for ( g4.reset(x0); f2.fn.counter<counter; )
    ++g4;
  cout << printvecfunc(g4.exp.xi,n) << endl;
  cout << SHOW(f2.fn.counter) << endl;
  cout << SHOW(f2.fmin) << endl;

  cout << "explorerand" << endl;
  explorerand< exploreh<probsysequ01,double*,double>, random00<> > g5(n,0.2,50000);
  for ( g5.reset(x0); g5.fn.counter<counter; )
    ++g5;
  cout << printvecfunc(g5.xi,n) << endl;
  cout << SHOW(g5.fn.counter) << endl;
  cout << SHOW(g5.fmin) << endl;

}










int main(int argc, char** argv)
{
  commandline cmd(argc,argv);
  uint prog(0);
  cmd.mapvar(prog,"prog");

  switch (prog)
  {
    case 0:
      cout << "Testing programs for pattern search optimization.";
      cout << endl << endl;
      cout << "$./main prog=1   - minimize a 3D parabola" << endl;
      cout << "$./main prog=2   - least squares fit of line segments" << endl;
      cout << "$./main prog=3   - solving a system of non linear equations" << endl;
      cout << "$./main prog=10  - pattern move with explorh" << endl;
      cout << "  options: counter=400 hstep=0.68" << endl;
      cout << "$./main prog=9   - pattern move with explorequad in dim dimensions" << endl;
      cout << "  options: counter=400 hstep=0.68 dim=30 average=2" << endl;
      cout << "$./main prog=13-15 - 1D line minimization test" << endl;
      cout << "$./main prog=20-22 - explore line test" << endl;
      cout << "$./man prog=16-17  - compare algorithms" << endl;
      cout << "$./main prog=50-54 - minexpdim" << endl;
      break;

    case 1: exploretest01(); break; 
    case 2: exploretest02(); break; 
    case 3: exploretest03(); break; 
    case 4: exploretest04(); break; 
    case 5: exploretest05(); break; 
    case 6: exploretest06(); break; 
    case 7: exploretest07(); break; 
    case 8: exploretest08(); break; 
    case 9: test09(argc,argv); break; 
    case 10: test08(argc,argv); break; 
    case 16: minimizecomparetest01(argc,argv); break; 
    case 17: minimizecomparetest02(argc,argv); break; 
    case 18: minimizecomparetest03(argc,argv); break; 


    case 12: partialderivativetest01(); break;
    case 35: lineoptimizergoldtest01(); break; 
//    case 36: lineoptimizergoldtest02(); break; 
//    case 37: lineoptimizergoldtest03(); break; 
//    case 38: lineoptimizergoldtest04(); break;
    case 20: explorelinetest01(argc,argv); break;
    case 21: explorelinetest02(argc,argv); break;
    case 22: explorelinetest03(argc,argv); break;
  
//    case 23: powelltest01(argc,argv); break; 
//    case 24: powelltest02(argc,argv); break; 

    case 30: explorepdtest01(argc,argv); break;
    case 31: explorepdtest02(argc,argv); break;

    case 50: minexpdimtest::test01(); break;
    case 51: minexpdimtest::test02(); break;
    case 52: minexpdimtest::test03(argc,argv); break;
    case 53: minexpdimtest::test04(argc,argv); break;
    case 54: minexpdimtest::test05(argc,argv); break;

    default: cout << "error:  No case handled." << endl; return 1;
  }

  return 0;
}




