#include <stdio.h>
#include <math.h> // fabs
#include "opti.hpp"
#include "keyboard.h"
#include <assert.h>

// This is a very simple optimization problem example.
// We try to find the square root of a number.
class SqrtProblem : public Opti::Problem {
private:
    double *minimum;
    double *maximum;
public:

    int getNumDimensions() {
	return 1; // Only one variable to solve
    }

    double *getMin() {
	return minimum; 
    }

    double *getMax() {
	return maximum; 
    }
    
    double costFunction(double *params, double compare) {
	// if x = square root of 2 then x*x should be 2
        // return how different x*x and 2 are by measuring the absolute error
	return fabs((params[0]*params[0]) - 2);       
    }

    // We need to solve the square root of the number given. That's our "problem".
    SqrtProblem(double number) {
	minimum = new double[1];
	maximum = new double[1];
	// We don't expect a square root to be negative
	minimum[0] = 0;
	// We don't expect the square root of a number to be greater than the number itself
	maximum[0] = number;
    }

    ~SqrtProblem() {
	delete[] minimum;
	delete[] maximum;
    }
};


int main() 
{
    INITKEYBOARD;
        
    SqrtProblem problem(2); // We wanna know the square root of 2
    
    Opti::Strategy *optimizer;
    
//	optimizer=new Opti::GreedyMagnus(&problem, 60, new Opti::PCXRecombinator(3));
//	optimizer=new Opti::GreedyMagnus(&problem, 60);
//	optimizer=new Opti::G3(&problem, 60, new Opti::MagnusRecombinator(5),2);
//	optimizer=new Opti::G3(&problem, 60);
//	optimizer=new Opti::DE(&problem, 60, new Opti::DERecombinator(0.999, 0.7));
    optimizer=new Opti::GreedyMagnus(&problem, 60);

    printf("\nOptimizing...\n\n");

    for(int t = 0;; t++) {
	if (!(t % 1)) {
	    double bestcost = optimizer->evolve();
	    printf("generation=%d, bestcost=%.20f, average %.20f\n", t, bestcost, optimizer->averageCost());
	    if (kbhit()) {
		printf("Parameter vector printout:\n");
		problem.print(optimizer->best());
		if (getch() == 27) break;
		getch();
	    }
	}
    }
    delete optimizer;

    DEINITKEYBOARD;
    return 0;
}

// FOR EMACS!!!
// Local Variables:
// compile-command: "g++ optitest.cpp opti.cpp -g"
// End:

