/*****************************************************************************
 *                                                                           *
 * FOX Controller Library, Version 1.3.3.                                    *
 *                                                                           *
 * Copyright (C) 1998,1999,2000 Russell Smith (rl.smith@auckland.ac.nz)      *
 *                                                                           *
 * The FOX Controller Library is free software; you can redistribute it      *
 * and/or modify it under the terms of the GNU Library General Public        *
 * License as published by the Free Software Foundation; either version      *
 * 2 of the License, or (at your option) any later version.                  *
 *                                                                           *
 * The FOX Controller Library is distributed in the hope that it will be     *
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of    *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
 * Library General Public License for more details.                          *
 *                                                                           *
 * You should have received a copy of the GNU Library General Public         *
 * License along with the Fox Controller Library; see the file COPYING.LIB.  *
 * If not, write to the Free Software Foundation, Inc., 59 Temple Place -    *
 * Suite 330, Boston, MA 02111-1307, USA.                                    *
 *                                                                           *
 *****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

#include "fox-n.h"


cftype frandom()
{
  return cftype(random())/cftype(RAND_MAX);
}


CmacInputInfo input_info[2] = {{65,0,1},{65,0,1}};



const cftype ka=0.2;
const cftype kb=1;
const cftype kh=0.1;

//const cftype ka=3;
//const cftype kb=0.75;
//const cftype kh=0.1;

//cftype Adata[1] = {0.96};
//cftype Bdata[1] = {0.04};
//cftype Cdata[1] = {1};

cftype Adata[4] = {1,kh,-ka*kh,1-kb*kh};
cftype Bdata[2] = {0,kh*ka};
cftype Cdata[2] = {1,0};


int main()
{
  srandom(1234567);
//  srandom(time(NULL));

  const int history = 200; // was 100
  const int C = 8;
  const int ny = 2;
  FoxN fox (2,input_info,40000,C,ny,Adata,Bdata,Cdata,history);
  fox.SetEligibilityMode (1);
  cftype input[2];

  // Training

  for (int i=0; i<200; i++) {
    input[0] = cftype(255-i)/256.0;
    input[1] = cftype(i)/256.0;
    int gate = (i % 100) > 50;
    fox.MapGate (input,gate);
    if (i==199) fox.Train (1);
    // else if (i==100) fox.Train (0.5);
    else fox.Train (0);
  }

/*
  for (int i=0; i<1000; i++) {
    input[0] = frandom();
    input[1] = frandom();
    cftype x = (input[0]-0.5)*5;
    cftype y = (input[1]-0.5)*5;
    target[0] = exp(-x*x - y*y);
    fox.Train (input,target,0.5);  <-- not correct anymore
  }
*/

/*
  cftype k = 0.9;			// filter constant
  input[0] = 0.5;
  input[1] = 0.5;
  cftype delta = 0.5;

  for (int i=0; i<1000; i++) {		// was 1000
    // random inputs
    input[0] = frandom();
    input[1] = frandom();
    delta = frandom();

    // filtered random inputs
    //    input[0] = k*input[0] + (1-k)*frandom();
    //    input[1] = k*input[1] + (1-k)*frandom();
    //    delta = k*delta + (1-k)*frandom();

    fox.Map (input);
    fox.Train (delta);
    // if ((i % 100)==99) fox.Reset();

//     if ((i % 30)==15) {
//       fox.SetEligibilityMode (0);
//       for (int j=0; j<10; j++) {
// 	input[0] = frandom();
// 	input[1] = frandom();
// 	fox.Map (input);
//       }
//       fox.SetEligibilityMode (1);
//     }
  }
*/

  // print out the result
  fox.SetEligibilityMode (0);
  for (int yy=0; yy<=64; yy++) {
    for (int xx=0; xx<=64; xx++) {
      input[0] = cftype(xx)/64.0;
      input[1] = cftype(yy)/64.0;
      fox.Map (input);

      // if (xx==50 && yy==50) printf ("%.16f ",2.0); else
      printf ("%.16f ",fox.Output());
    }
    printf ("\n");
  }

  return 0;
}
