#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;
using namespace mmgd;

int main(void)
{
try{
int N=5;
smatrix A(N,N);
smatrix B(N,N);
smatrix C(N,N);
smatrix As, AsAs;
smatrix Cs,Bs;
poly p;
p.init(10,7)(14,8)(15,11)(17,14)(19,16)(20,18);
poly q;
q.init(23,30)(26,34)(30,38)(31,41)(35,43)(38,46)(41,49)(42,53);
gd r;
r.init(22,25);
serie s;
s.init(p,q,r);
serie sstar, sstarstar,sstarsstar;

sstar=star(s);
cout<<"sstar "<<sstar<<endl;

sstarstar=otimes(sstar,sstar);

if(sstar==sstarstar)
cout<<" Yes Sstar == sstarstar"<<endl;
else
    {
    cout<<"sstarstar "<<sstarstar<<endl;
    }
sstarstar=star(sstar);
if(sstar==sstarstar)
cout<<" Yes Sstar == sstarstar"<<endl;
else
    {
    cout<<"sstarstar "<<sstarstar<<endl;
    }
int i=330000;
poly ptest;

int j,k;
int L=5;
int gamma,delta;
srand(time(NULL));
poly w;
p.init(rand()%L,rand()%L)(rand()%L,rand()%L)(rand()%L,rand()%L)(rand()%L,rand()%L)(rand()%L,rand()%L)(rand()%L,rand()%L);
q.init(rand()%L,rand()%L)(rand()%L,rand()%L)(rand()%L,rand()%L)(rand()%L,rand()%L)(rand()%L,rand()%L)(rand()%L,rand()%L);
w.init(rand()%L,rand()%L)(rand()%L,rand()%L)(rand()%L,rand()%L)(rand()%L,rand()%L)(rand()%L,rand()%L)(rand()%L,rand()%L);
p=epsilon;
q=epsilon;
w=epsilon;
p.init(rand()%L,rand()%L);
q.init(rand()%L,rand()%L);
w.init(rand()%L,rand()%L);
gd m;
poly p1,p2,p3,p4;
serie s1,s2,s3;
for (k=0;k<8;k++)
{
for(i=0;i<1;i++)
{   gamma=rand()%L+p.getpol(p.getn()-1).getg();
    delta=gamma+rand()%L+p.getpol(p.getn()-1).getd();
    m=gd(gamma,delta);

    p=oplus(p,m);
    gamma=rand()%L+q.getpol(q.getn()-1).getg();
    delta=gamma+rand()%L+q.getpol(q.getn()-1).getd();
    m=gd(gamma,delta);

     q=oplus(q,m);

      gamma=rand()%L+w.getpol(w.getn()-1).getg();
    delta=gamma+rand()%L+w.getpol(w.getn()-1).getd();
    m=gd(gamma,delta);

     w=oplus(w,m);
    w.simpli();
    p.simpli();
    q.simpli();

}
cout<<"p.getn()"<<p.getn()<<endl;
cout<<"q.getn()"<<q.getn()<<endl;
cout<<"w.getn()"<<w.getn()<<endl;

cout<<"oplus test "<<k<<endl;
    p1=oplus(p,q);
    p2=oplus(q,w);
    p3=oplus(p1,w);
    p4=oplus(p,p2);
    if(!(p3==p4))
    {
        cout<<"pb p3 "<<p3<<endl<<endl;
        cout<<"pb p4 "<<p4<<endl<<endl;
        getchar();
    }
    p3=oplus(p4,p);

    if(!(p3==p4))
    {
        cout<<"pb p3 "<<p1<<endl<<endl;
        cout<<"pb p4 "<<p2<<endl<<endl;
        getchar();
    }

cout<<"otimes test "<<k<<endl;
    p1=otimes(p,q);
    p2=otimes(q,w);
    p3=otimes(p1,w);
    p4=otimes(p,p2);
    if(!(p3==p4))
    {
        cout<<"pb p3 "<<p4<<endl<<endl;
        cout<<"pb p4 "<<p4<<endl<<endl;
        getchar();
    }
    p3=otimes(q,p);
    p4=otimes(w,q);
    if(!(p1==p3))
    {
        cout<<"pb p1 "<<p1<<endl<<endl;
        cout<<"pb p3 "<<p3<<endl<<endl;
        getchar();
    }
    if(!(p2==p4))
    {
        cout<<"pb p2 "<<p2<<endl<<endl;
        cout<<"pb p4 "<<p4<<endl<<endl;
        getchar();
    }
cout<<"star test "<<k<<endl;
    s1=star(p);
    s2=otimes(s1,s1);
   if(!(s1==s2))
    {
        cout<<"pb s1 "<<s1<<endl<<endl;
        cout<<"pb s2 "<<s2<<endl<<endl;
        getchar();
    }

    s3=star(s1);
   if(!(s3==s1))
    {
        cout<<"pb s3 "<<s3<<endl<<endl;
        cout<<"pb s1 "<<s1<<endl<<endl;
        getchar();
    }




gd m;


for(i=0;i<N;i++)
{
    for(j=0;j<N;j++)
    {
        A(i,j)=otimes(p,m=gd(rand()%10+1,rand()%10+1));
         B(i,j)=otimes(q,m=gd(rand()%10+1,rand()%10+1));
          C(i,j)=otimes(w,m=gd(rand()%10+1,rand()%10+1));
    }
}
cout<<" A "<< A<<endl;

As=star(A);
Bs=star(B);
Cs=star(C);

smatrix Aplus,Bplus,Cplus,Dplus;

Aplus=oplus(As,Bs);
Bplus=oplus(Bs,As);
Cplus=oplus(Aplus,Cs);
Dplus=oplus(Bplus,Cs);
if(Cplus==Dplus)
{
    cout<<" Oplus matrix ok"<<endl;
}
else
{

  for(i=0;i<N;i++)
    for(j=0;j<N;j++)
  {
      {
          if(!(Cplus(i,j)==Dplus(i,j)))
          {
              cout<<"Cplus"<<i<<j<<"***"<<Cplus(i,j)<<endl;
    cout<<"******"<<endl;
cout<<"Dplus"<<i<<j<<"***"<<Dplus(i,j)<<endl;
cout<<"******"<<endl;
          }
      }
  }

}

cout<<"As "<<As<<endl;
getchar();
cout<<"Bs "<<Bs<<endl;
cout<<"Cs "<<Cs<<endl;

AsAs=otimes(As,As);

cout<<"BEfore 12/2018"<<endl;
if(AsAs==As)

{

 cout<<"Yes ASAS==AS"<<endl;
 AsAs=star(As);
 if(AsAs==As)

{

 cout<<"Yes ASStar==AS"<<endl;
}

    else
    { cout<<"No"<<endl;
    cout<<"As"<<As<<endl;
    cout<<"******"<<endl;
cout<<"AsAs"<<AsAs<<endl;

  for(i=0;i<N;i++)
    for(j=0;j<N;j++)
  {
      {
          if(!(As(i,j)==AsAs(i,j)))
          {
              cout<<"As"<<i<<j<<"***"<<As(i,j)<<endl;
    cout<<"******"<<endl;
cout<<"AsAs"<<i<<j<<"***"<<AsAs(i,j)<<endl;
cout<<"******"<<endl;
          }
      }
  }
    }
}
else{ cout<<" Pb AsAs!=As)"<<endl;}
}
//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);
 }
}
