/// @file: 	optimization/SimpleOptTestGrid.cpp
/// @author:	Matthias Wacker
/// @date:	2009-10-05

#include "SimpleOptTestGrid.h"

using namespace std;
using namespace OPTIMIZATION;

SimpleOptTestGrid::SimpleOptTestGrid()
{
  m_iNumberOfOptimizers = 0;
  m_iNumberOfProblems = 0;
}


SimpleOptTestGrid::~SimpleOptTestGrid()
{
}


void SimpleOptTestGrid::addSimpleOptProblem(const SimpleOptProblem & optProb, const OPTIMIZATION::matrix_type &solution, double successDist)
{
  m_vSimpleOptProblem.push_back(optProb);
  m_vSolutions.push_back(solution);
  m_vSuccessDistances.push_back(successDist);

  m_iNumberOfProblems = m_vSimpleOptProblem.size();
}


void SimpleOptTestGrid::addSimpleOptimizer(SimpleOptimizer *opt)
{
  m_vSimpleOptimzers.push_back(opt);
  m_iNumberOfOptimizers = m_vSimpleOptimzers.size();
}


bool SimpleOptTestGrid::test()
{
  bool success = true;

  // for every optimizer
  for(int optIdx=0; optIdx < m_iNumberOfOptimizers; ++optIdx)
  {
    // run every test
    for(int probIdx=0; probIdx < m_iNumberOfProblems; ++probIdx)
    {
      bool tmpResult = test(optIdx,probIdx);
      cout << "SOTG: single test with opt: " << optIdx << " and prob: " << probIdx;
      if(tmpResult == true)
      {
        cout << " SUCCEEDED"<<endl; 
      }
      else
      {
        cout << " FAILED"<<endl;
      }

    }
  }

  return success;
}



bool SimpleOptTestGrid::test(int optIdx, int probIdx)
{
  // get a copy of the prob
  SimpleOptProblem optProb = m_vSimpleOptProblem[probIdx];
  matrix_type init = optProb.getAllCurrentParams();
  
  // start Optimization
  m_vSimpleOptimzers[optIdx]->optimizeProb(optProb);

  // check for success
  matrix_type result = optProb.getAllCurrentParams();
  double distres = ( result - m_vSolutions[probIdx] ).frobeniusNorm();
  double distinit = ( init - m_vSolutions[probIdx] ).frobeniusNorm();

  cout << "resDist: "<< distres << " from initial: "<< distinit << endl;

  return distres < m_vSuccessDistances[probIdx];
}