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



/////////////////////////////////////////////////////////////////////
/* Example : Discrete Event Systems in Dioid Framework : Control Theory
 Laurent Hardouin, Olivier Boutin, Bertrand Cottenceau, Thomas Brunsch, Joerg Raisch
 Springer, DISC Book
This program compute :
1. the optimal control when a reference output is a priori known
2. the optimal input filtering when the reference output is unknown
3. the optimal feedback
*/
#include "..\src\gd.cpp"
#include "..\src\poly.cpp"
#include "..\src\serie.cpp"
#include "..\src\smatrix.cpp"
#include "..\src\tools.cpp"


using namespace std;

int main(void)
{
try{

smatrix a(10,10), as(10,10),b(10,3), c(1,10), u(3,1), y(1,1), asb(10,3), casb(1,3);
smatrix z (1,1);
poly p;


// the system, matrix a
a(1,0)=gd(0,7);
a(2,1)=gd(0,1);

a(4,3)=gd(0,1);
a(5,4)=gd(0,1);
a(6,5)=gd(0,12);

a(8,7)=gd(0,5);
a(9,8)=gd(0,1);

a(0,2)=gd(1,0);
a(3,6)=gd(2,0);
a(7,9)=gd(1,0);

a(4,1)=gd(0,0);
a(1,4)=gd(0,0);
a(5,8)=gd(0,0);

// the system matrix b
b(0,0)=gd(0,0);
b(3,1)=gd(0,0);
b(7,2)=gd(0,0);

// the system matrix c
c(0,6)=gd(0,0);

// the star of the matrix a
as= star(a);

asb = otimes(as,b); // transfer matrix between input and state vector
casb = otimes(c,asb); // trnasfer matrix between input and output
cout<<"Transfer of the system CA*B \n"<<casb<<endl;
// reference output, the desired date for 4 parts
z(0,0).init(epsilon,p.init(0,37)(1,42)(3,55)(4,infinity),e);

smatrix uopt=lfrac(z,casb); // optimal control
smatrix yopt=otimes(casb,uopt); // optimal output
cout<<"Reference output\n z= \n"<<z<<endl;
cout<<"Optimal control\n u_opt \n"<<uopt<<endl;
cout<<"Optimal output\n y_opt \n"<<yopt<<endl;

smatrix Popt; //the optimal filter
smatrix Fopt; // the optima feedback

Popt=lfrac(casb,casb);
cout<<"Optimal Filter non causal\n P_opt \n"<<Popt<<endl;
Popt=prcaus(Popt);
cout<<"Optimal Filter causal\n P_opt \n"<<Popt<<endl;

Fopt=rfrac(Popt,Popt);
Fopt=rfrac(Fopt,casb);
cout<<"Optimal Feedback non Causal \n Fopt \n"<<Fopt<<"\n";
Fopt=prcaus(Fopt);
cout<<"Optimal Feedback non Causal \n Fopt \n"<<Fopt<<"\n";



//fstream f;

//  f.open("/home/brunsch/CAsB.txt",ios::out);
//f<<casb;
//f.close();

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