#ifndef _WIN32
#include "../include/lminmaxgd.h"
#else
#include "..\include\lminmaxgd.h"
using namespace std;
#endif
/////////////////////////////////////////////////////////////////////
/* Example : Automatica 2001, to appear
           "Model reference control for timed event graphs in dioids"
// you must link with a library which contains all source files given in folder src
// gd.cpp poly.cpp serie.cpp smatrix.cpp tools.cpp interf.cpp
// or add these files in your project
// or alternatively you can include the folowing files
//
*/
#include "..\src\gd.cpp"
#include "..\src\poly.cpp"
#include "..\src\serie.cpp"
#include "..\src\smatrix.cpp"
#include "..\src\tools.cpp"

/////////////////////////////////////////////////////////////////////


int main()
{
try
{
/////////////////////////////////////////////////////////////////////\\
// Backward Equations , Optimal control \\
/////////////////////////////////////////////////////////////////////

   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 u_opt; // control law
   smatrix y_opt; // output when u_opt is applied
   smatrix z(1,1); // the desired output


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

    cout<<"\n The model (transfer function) H \n"<<H;


    //output trajectory desired : z >= y=h*u
    poly ptemp; //temporay polynomial

    ptemp.init(0,30)(1,32)(2,32)(3,infinity);
    z(0,0) = ptemp;


    //Optimal command (denoted u_opt) : u_opt = H \z
    u_opt = lfrac(z,H);


    //Ouput y=h*u_opt
    y_opt = otimes(H,u_opt);
    //which is less than or equal to z
    cout<<"\n the desired output z \n"<<z<<endl;
    cout<<"\n the optimal input u_opt \n"<<u_opt;
    cout<<"\n the optimal output y_opt \n"<<y_opt<<endl;


	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);
 }
}
