#ifndef _WIN32
#include "../include/lminmaxgd.h"
#else
#include "..\include\lminmaxgd.h"
using namespace std;
#endif
#include <time.h>




/////////////////////////////////////////////////////////////////////
/* Example :

*/
#include "..\src\gd.cpp"
#include "..\src\poly.cpp"
#include "..\src\serie.cpp"
#include "..\src\smatrix.cpp"
#include "..\src\tools.cpp"

int main()
{
try
{
   smatrix   A(6,6); // state matrix 6x6
   smatrix   B(6,2); // input matrix 6x2, 2 inputs
   smatrix  C(1,6);  // output matrix 1x6, 1 output
   smatrix  H; // transfer matrix, the dimension will be defined automatically
   smatrix Gref(1,2); // reference model to match 1x2, 2 inputs 1 output
   smatrix P_opt; // Filter matrix
   smatrix Hc; // transfer with the filter
   smatrix v(2,1); // input of the system
   smatrix u(2,1); // control law
   smatrix y_HP; // output when when u=Pv, with filter
   smatrix y_H; // output when when u=v, without filter


    //state matrix declaration
    A(0,1)=gd(1 ,0); // 1 token and 0 time unit  between x_2 and x_1
    A(1,0)=gd(0 ,2); // 0 token and 2 time units between x_1 and x_2

    A(2,3)=gd(1 ,0); // 1 token and 0 time unit between x_4 a,d x_3
    A(3,2)=gd(0, 3);

    A(4,1)=gd(0, 0);
    A(4,3)=gd(0, 0);
    A(4,5)=gd(1, 0);
    A(5,4)=gd(0 ,2);

    //Input and Output matrices
    B(0,0)=gd(0, 0);
    B(2,1)=gd(0, 0);

    C(0,5)=gd(0 ,0);


    //Transfer matrix
    smatrix As;
    smatrix CAs;
    As=star(A);
    CAs=otimes(C,As);
    H = otimes(CAs,B);

    Gref=H;

    //Optimal precompensator (denoted P_opt) : P_opt = H \Gref
    P_opt =lfrac(Gref, H);

    //transfer of corrected system Ouput Hc=H*P_opt
    Hc = otimes(H,P_opt);


    cout<<"\n The model (transfer function) H \n"<<H;
    cout<<"\n The model to match Gref \n"<<Gref;
    cout<< "\n The filter (transfer function) Popt=H\\Gref \n"<<P_opt;
    cout<<"\n The model achieved Hc\n"<<Hc; //which is less than or equal to Gref, but the best than we can do
    cout<<"\n It appears that Gref==Hc \n";


    // For a control v (3 tokens on each input at time zero
    poly ptemp; //temporay polynomial
    ptemp.init(0,0)(1,0)(2,0)(3,infinity);
    v(0,0)=ptemp; // the polynom is put as a series in the component of vector v
    v(1,0)=ptemp;

    // output with control applied without precompensator
    u=v;
    y_H=otimes(H,u);

    cout<<"\n u= v \n"<<u;
    cout<<"\n y_H = Hu, output without filter \n "<<y_H;

    // output with optimal control, it is the same than without
    u=otimes(P_opt,v);
    y_HP=otimes(H,u);
    cout<<"\n u= Pv, the control law \n "<<u;
    cout<<"\n y_HP = Hc v=HP v, output with filter \n "<<y_HP;

    cout<<"\n Clearly y_H == y_HP, but Pv >= v, the input is delayed as much as possible \n";

	return(0);
}

 catch(mem_limite l)
 {
	 cout<<"Exception : too many coefficent in polynom "<<l.memoire<<endl;
	 return(1);
 }

 catch(taille_incorrecte obj)
 { // 0 : r non causal
   // 1 : tentative d'accès à un element d'une matrice avec un indice incorrect
   // 2 : matrice de taille incompatible pour oplus, inf, otimes, rfrac, lfrac
   // 3 : etoile de matrice carré uniquement
	 cout<<"Exception  "<<obj.erreur<<endl;
	 return(1);
 }
}
