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

#include <exploretest.h>

#include <print.h>
#include <dumbarray.h>

#include <exploreh.h>
#include <leastsqrs.h>
#include <probparab.h>
#include <probsysequ01.h>
#include <probrosenbrock.h>


void exploretest01()
{
  uintc n(3);
  exploreh<probparab,double*,double> g(n);
  double xi[n];
  g.xiSet((double*)xi);

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

  g.indexmax = 50;
  for (g.reset(x0); !g; ++g)
    cout << print<double*>(g.xi,g.xi+n) << endl;
    //cout << printvec<double*>(g.xi,n) << endl;

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

}

void exploretest02()
{
  vector<pt2> pts;

  uintc psz =7;
  double const parray[2*psz] = 
  {
    0.0, 0.0,
    1.0, 1.1,
    1.5, 2.8,
    2.8, 4.2,
    4.8, 4.0,
    6.8, 4.2,
    8.1, 5.5
  };

  for (uint i=0; i<psz; ++i)
    pts.push_back( pt2(parray[i*2],parray[i*2+1]) );

  leastsqrs fn(pts);
  
  exploreh<leastsqrs &,double*,double> g(fn,psz);

  double x0[psz];
  for (uint i=0; i<psz; ++i)
    x0[i] = pts[i].y;

  //g.h0Set(1.52E-5);

  g.indexmax = 50;

  for (g.reset(x0); !g; ++g)
  {
    g.print(cout) << endl;
  }

  cout << endl << endl;


  cout << "The result" << endl;
  for (uint i=0; i<psz; ++i)
  {
    cout << pts[i].x << " " << g.xi[i] << endl;
  }

}

void exploretest05()
{

  probparab2 fn;
  exploreh<probparab2 &,double*,double> g(fn,3);

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

  g.indexmax = 50;
  for (g.reset(x0); !g; ++g)
    cout << g.xi[0] << " " << g.xi[1] << " " << g.xi[2]  << endl;

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

}

void exploretest06()
{
  exploreh<probparab2,double*,double> g(3);

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

  g.indexmax = 50;
  for (g.reset(x0); !g; ++g)
    cout << g.xi[0] << " " << g.xi[1] << " " << g.xi[2]  << endl;

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

void exploretest04()
{
  cout << "Testing the hasStateChanged variable in exploreh" << endl;
  cout << "Looking at d xi" << endl;
  exploreh<probparab2,double*,double> g(3);

  double x0[3] = { 0.0, 0.0, 0.0 };
  double x1[3];

  g.indexmax = 50;
  g.reset(x0);
  double dist;
  for (g.reset(x0); !g; ++g)
  {
    if (g.hasStateChanged)
    {
      dist=0.0;
      for (uint k=0; k<3; ++k)
      {
        x1[k] = g.xi[k]-x0[k];
        dist += x1[k]*x1[k];
        x0[k] = g.xi[k];
      }
      cout << SHOW(dist) << endl;
    }
  }
  cout << g.xi[0] << " " << g.xi[1] << " " << g.xi[2]  << endl;
  cout << SHOW(g.fn.counter) << endl;
  cout << "The exact solution is (1,2,5)" << endl;
}

void exploretest07()
{
  exploreh<probparab3,dumbarray<double>,double> g(3);
  double x0[3] = { 0.0, 0.0, 0.0 };

  g.indexmax = 50;
  for (g.reset(x0); !g; ++g)
    cout << g.xi[0] << " " << g.xi[1] << " " << g.xi[2] << endl;

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





void exploretest03()
{
  cout << "This test is to solve a non-linear system of equations" << endl;
  cout << " numerically and terminate the approximation when the" << endl;
  cout << " parital derivatives become small." << endl;
  exploreh<probsysequ01,double*,double> g(2,0.2,50000);

  double x0[2] = { 0.5, 0.5 };

  g.reset(x0);

  g.print(cout);


  double zero = 1e-5;
  cout << "Iterate until the partial derivative are less than" << endl;
  cout << " " << zero << " in magnitude." << endl;
  bool valid=true;

  double pd[2];

  for (uint i=0; valid; ++i)
  {
    g.fn.partialderivative(pd[0],0,g.hi[0]);
    g.fn.partialderivative(pd[1],1,g.hi[1]);
    if (zero>(abs(pd[0])+abs(pd[1])))
      valid=false;

cout << SHOW(i) << endl;
    ++g;

  }

  g.print(cout);
  cout << SHOW(g.fn.counter) << endl;

}

void exploretest08()
{
  uintc n(2);
  exploreh<probrosenbrock01,double*,double> g(n);
  double xi[n];
  g.xiSet((double*)xi);

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

  cout << "Enter initial point" << endl;
  cin >> x0[0] >> x0[1];

  g.indexmax = 80;
  uint i=1;
  uintc ireset=300;

  for (g.reset(x0); !g; ++g)
  {
    if (i%ireset==0)
    { 
      cout << "resetting g" << endl;
      g.reset();
    }
    ++i;

    g.print(cout);

    //cout << printvec<double*>(g.xi,n) << endl;
  }

  cout << SHOW(g.fn.counter) << endl;
  cout << SHOW(g.fmin) << endl;

  cout << "The exact solution is (1,1)" << endl;

}



