#ifndef _WIN32
#include "../include/lminmaxgd.h"
#else
#include "..\include\lminmaxgd.h"
using namespace std;
#endif
/////////////////////////////////////////////////////////////////////
/* Example : Closed Loop control, synthesis of the filter and of the feedback
controller
*/
#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 F_opt; // Filter matrix


    //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, 5);

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

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

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


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

    Gref=H;
    serie temp;
    gd r(1,5);
    temp.init(epsilon,e,r);
    Gref(0,0)=otimes(temp,Gref(0,0));
    Gref(0,1)=otimes(temp,Gref(0,1));

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


    cout<<"\n The model (transfer function) H \n"<<H;
    cout<<"\n The model to match Gref \n"<<Gref;
    cout<<" Popt non  causal  "<<P_opt<<endl;

    smatrix Popt_causal=prcaus(P_opt);
    cout<<" Popt  causal  "<<Popt_causal<<endl;

    cout<<" Fopt non causal"<<F_opt<<endl; // the state feedback controller
    smatrix  F_opt_causal=prcaus(F_opt);
    cout<<" Fopt causal"<<F_opt_causal<<endl;

	return(0);
}

 catch(mem_limite l)
 {
	 cout<<"Exception : too many coefficents 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ée uniquement
	 cout<<"Exception  "<<obj.erreur<<endl;
	 return(1);
 }
}
