https://hal.archives-ouvertes.fr/hal-02177293
Tip revision: a5c3a632ff52caf942ac0457ce1ec733926a867b authored by Software Heritage on 01 January 2004, 00:00:00 UTC
hal: Deposit 315 in collection hal
hal: Deposit 315 in collection hal
Tip revision: a5c3a63
MoteurDD2.java
/*
* Créé le 10 juin 2004
*
*/
package traitement.moteur;
import information.DomaineIncompatibleException;
import information.magnitude.Magnitude;
import information.tpt.TPT;
import information.type.Type;
import jama.EigenvalueDecomposition;
import jama.Matrix;
import java.io.IOException;
import java.util.Vector;
import principal.copiercoller.HomonymeIntrouvableException;
import principal.copiercoller.InterfaceHomonyme;
import traitement.TraitementEvent;
import traitement.TraitementIncompletException;
import traitement.TraitementListener;
import traitement.modele.Modele;
import traitement.noeud.InterfaceNoeud;
import traitement.noeud.fonctionnel.NoeudFonctionnelEndogene;
import traitement.noeud.fonctionnel.NoeudFonctionnelExogene;
import traitement.noeud.fonctionnel.VectorNoeudFonctionnel;
import fichier.ContenuFichierIncompatibleException;
import fonction.magnitude.MagnitudeBruit;
import fonction.magnitude.VectorFonctionFilsMagnitude;
import gui.InterfaceAffichable;
/**
* adaptation du filtre ŕ différences divisées du second ordre (DD2) de Magnus Norgaard.
*
* @author Vincent Labatut
* @version 1
* @see traitement.modele.Modele
*/
public class MoteurDD2 implements InterfaceMoteur
{
// ----------------------------------------
// Moteur
// ----------------------------------------
/**
* Liste des TraitementListeners écoutant cette Moteur.
*
*/
private Vector vectorTraitementListener;
/**
* Modele parent de ce Moteur.
*
*/
private Modele parent;
/**
* indique si cet objet a été modifé depuis sa derničre sauvegarde.
*/
private boolean modifie;
// ----------------------------------------
// Listes de Noeuds
// ----------------------------------------
/**
* Liste des NoeudExogenes utilisée pendant le traitement.
*
*/
private VectorNoeudFonctionnel vectorNoeudExogene;
/**
* Liste des NoeudEndogenes non observés pour l'activation, utilisée pendant le traitement.
*
*/
private VectorNoeudFonctionnel vectorNoeudEndogeneActivation;
/**
* Liste des NoeudEndogenes non observés pour l'émission, utilisée pendant le traitement.
*
*/
private VectorNoeudFonctionnel vectorNoeudEndogeneEmission;
/**
* Liste des NoeudEndogenes observés pour l'activation, utilisée pendant le traitement.
*
*/
private VectorNoeudFonctionnel vectorNoeudObserveActivation;
/**
* Liste des NoeudEndogenes observés pour l'émission, utilisée pendant le traitement.
*
*/
private VectorNoeudFonctionnel vectorNoeudObserveEmission;
// ----------------------------------------
// Listes de bruits
// ----------------------------------------
/**
* Liste des bruits de traitement pour l'activation, utilisée pendant le traitement.
*
*/
private VectorFonctionFilsMagnitude vectorBruitTraitementActivation;
/**
* Liste des bruits de traitement pour l'émission, utilisée pendant le traitement.
*
*/
private VectorFonctionFilsMagnitude vectorBruitTraitementEmission;
/**
* Liste des bruits de mesure pour l'activation, utilisée pendant le traitement.
*
*/
private VectorFonctionFilsMagnitude vectorBruitMesureActivation;
/**
* Liste des bruits de mesure pour l'émission, utilisée pendant le traitement.
*
*/
private VectorFonctionFilsMagnitude vectorBruitMesureEmission;
// ----------------------------------------
// Dimensions
// ----------------------------------------
/**
* dimension de la variable d'entrée (ie nbre de NoeudExogenes)
*
*/
private int nu;
/**
* dimension de la variable d'état (ie nbre de NoeudEndogenes non-observés)
*
*/
private int nxA;
/**
* dimension de la variable d'état (ie nbre de NoeudEndogenes non-observés)
*
*/
private int nxE;
/**
* dimension de la variable de sortie ou observée (ie nbre de NoeudEndogenes observés)
*
*/
private int nyA;
/**
* dimension de la variable de sortie ou observée (ie nbre de NoeudEndogenes observés)
*
*/
private int nyE;
/**
* dimension de la matrice de covariance de bruit (ie nbre de sources de bruit dans les NoeudEndogenes non-observés)
*
*/
private int nvA;
/**
* dimension de la matrice de covariance de bruit (ie nbre de sources de bruit dans les NoeudEndogenes non-observés)
*
*/
private int nvE;
/**
* dimension de la matrice de covariance de bruit observée (ie nbre de sources de bruit dans les NoeudEndogenes observés)
*
*/
private int nwA;
/**
* dimension de la matrice de covariance de bruit observée (ie nbre de sources de bruit dans les NoeudEndogenes observés)
*
*/
private int nwE; //
// ----------------------------------------
// Divers
// ----------------------------------------
/**
* Squared divided-difference step size
*
*/
private double h2;
/**
* Divided difference step-size
*
*/
private double h;
/**
* A convenient scaling factor
*
*/
private double scal1;
/**
* Another scaling factor
*
*/
private double scal2;
// ----------------------------------------
// Matrices
// ----------------------------------------
/**
* Matrice d'état a posteriori
*
*/
private Matrix xhat;
/**
* Matrice d'état a priori
*
*/
private Matrix xbar;
/**
* Matrice de covariance triangulaire
*
*/
private Matrix Sx;
/**
* Matrice de covariance triangulaire
*
*/
private Matrix Sxbar;
/**
* Matrice de covariance triangulaire
*
*/
private Matrix SxxSxv;
/**
* Matrice de covariance triangulaire
*
*/
private Matrix SyxSyw;
/**
* Matrice de bruits
*
*/
private Matrix wmean;
/**
* Matrice de bruits
*
*/
private Matrix vmean;
/**
* Matrice de bruits
*
*/
private Matrix hSv;
/**
* Matrice de bruits
*
*/
private Matrix hSw;
/**
* Matrice d'historique
*
*/
private Matrix Smat;
/**
* Matrice d'historique
*
*/
private Matrix sidx;
/**
* indices
*
*/
private int nxnv2;
/**
* indices
*
*/
private int nxnw2;
/**
* indices
*
*/
private int idx_syw2;
/**
* indices
*
*/
private int idx_sxv2;
// ----------------------------------------
// Constructeurs
// ----------------------------------------
/**
* Constructeur pour créer un Moteur
* de parent le Modele
* passé en paramčtre.
*
* @param m parent de ce Moteur.
*
*/
public MoteurDD2(Modele m)
{ parent = m;
vectorTraitementListener = new Vector();
setModifie();
}
// ----------------------------------------
// Parent
// ----------------------------------------
/*
*
*/
public Modele getParent()
{ return parent;
}
/*
*
*/
public void setParent(Modele p)
{ parent = p;
}
// ----------------------------------------
// Modele
// ----------------------------------------
/*
*
*/
public Modele getModele()
{ return parent;
}
// ----------------------------------------
// InterfaceTraitement
// ----------------------------------------
/*
*
*/
public void addTraitementListener(TraitementListener i)
{ vectorTraitementListener.add(i);
}
/*
*
*/
public void removeTraitementListener(TraitementListener i)
{ vectorTraitementListener.remove(i);
}
/**
* annonce la suppression de cette Distance.
* Chaque TraitementListener doit se supprimer lui-męme de la liste des listeners de cette Distance.
*
* @param e le TraitementEvent qui est émis vers les TraitementListeners.
*/
private void fireTraitementSuppr(TraitementEvent e)
{
while (vectorTraitementListener.size()!=0)
try
{ ((TraitementListener) vectorTraitementListener.get(0)).traitementSuppr(e);
}
catch (TraitementIncompletException e1)
{ e1.printStackTrace();
}
}
/**
* annonce un raffraichissement de cette Distance.
*
* @param e le TraitementEvent qui est émis vers les TraitementListeners.
*/
private void fireTraitementRaffr(TraitementEvent e)
{
for (int i=0;i<vectorTraitementListener.size();i++)
try
{ ((TraitementListener) vectorTraitementListener.get(i)).traitementRaffr(e);
}
catch (TraitementIncompletException e1)
{ e1.printStackTrace();
}
}
/**
* annonce un raffraichissement de cette Distance.
*
* @param e le TraitementEvent qui est émis vers les TraitementListeners.
*/
private void fireTraitementRempl(TraitementEvent e)
{ for (int i=0;i<vectorTraitementListener.size();i++)
try
{ ((TraitementListener) vectorTraitementListener.get(i)).traitementRempl(e);
}
catch (TraitementIncompletException e1)
{ e1.printStackTrace();
}
}
/**
* annonce un raffraichissement de cette Distance.
*
* @param e le TraitementEvent qui est émis vers les TraitementListeners.
*/
private void fireTraitementCache(TraitementEvent e)
{ for (int i=0;i<vectorTraitementListener.size();i++)
try
{ ((TraitementListener) vectorTraitementListener.get(i)).traitementCache(e);
}
catch (TraitementIncompletException e1)
{ e1.printStackTrace();
}
}
//----------------------------------------
// This
//----------------------------------------
/*
*
*/
public void remove()
{ fireTraitementSuppr(new TraitementEvent(this));
//
parent = null;
//
}
// ----------------------------------------
// Simulation
// ----------------------------------------
/*
*
*/
public boolean estComplet()
{ return true;
}
/*
*
*/
public void preparerSimulation()
{
//NOTE tester la présence d'au moins un noeudEndogene ? non-observable ?
//NOTE tester la présence de bruit ?
VectorNoeudFonctionnel vectorNoeudFonctionnel = parent.getVectorNoeudFonctionnel();
// déterminer la liste de NoeudFonctionnelEndogene et celle de NoeudFonctionnelExogene
// et la liste des sources de bruit
vectorNoeudExogene = new VectorNoeudFonctionnel();
vectorNoeudEndogeneActivation = new VectorNoeudFonctionnel();
vectorNoeudEndogeneEmission = new VectorNoeudFonctionnel();
vectorNoeudObserveActivation = new VectorNoeudFonctionnel();
vectorNoeudObserveEmission = new VectorNoeudFonctionnel();
vectorBruitTraitementActivation = new VectorFonctionFilsMagnitude();
vectorBruitTraitementEmission = new VectorFonctionFilsMagnitude();
vectorBruitMesureActivation = new VectorFonctionFilsMagnitude();
vectorBruitMesureEmission = new VectorFonctionFilsMagnitude();
for (int i=0;i<vectorNoeudFonctionnel.size();i++)
{ InterfaceNoeud n = vectorNoeudFonctionnel.getNoeudFonctionnel(i);
if (n instanceof NoeudFonctionnelEndogene)
{ if (((NoeudFonctionnelEndogene) n).estObservableActivation())
{ vectorNoeudObserveActivation.addNoeudFonctionnel((NoeudFonctionnelEndogene)n);
VectorFonctionFilsMagnitude temp = ((NoeudFonctionnelEndogene)n).getSectionActivation().getFonctionMagnitude().getMagnitudeBruit();
for (int j=0;j<temp.size();j++)
vectorBruitMesureActivation.addInterfaceFonctionFilsMagnitude(temp.getInterfaceFonctionFilsMagnitude(j));
}
else
{ vectorNoeudEndogeneActivation.addNoeudFonctionnel((NoeudFonctionnelEndogene)n);
VectorFonctionFilsMagnitude temp = ((NoeudFonctionnelEndogene)n).getSectionActivation().getFonctionMagnitude().getMagnitudeBruit();
for (int j=0;j<temp.size();j++)
vectorBruitTraitementActivation.addInterfaceFonctionFilsMagnitude(temp.getInterfaceFonctionFilsMagnitude(j));
}
if (((NoeudFonctionnelEndogene) n).estObservableEmission())
{ vectorNoeudObserveEmission.addNoeudFonctionnel((NoeudFonctionnelEndogene)n);
VectorFonctionFilsMagnitude temp = ((NoeudFonctionnelEndogene)n).getSectionEmission().getFonctionMagnitude().getMagnitudeBruit();
for (int j=0;j<temp.size();j++)
vectorBruitMesureEmission.addInterfaceFonctionFilsMagnitude(temp.getInterfaceFonctionFilsMagnitude(j));
}
else
{ vectorNoeudEndogeneEmission.addNoeudFonctionnel((NoeudFonctionnelEndogene)n);
VectorFonctionFilsMagnitude temp = ((NoeudFonctionnelEndogene)n).getSectionEmission().getFonctionMagnitude().getMagnitudeBruit();
for (int j=0;j<temp.size();j++)
vectorBruitTraitementEmission.addInterfaceFonctionFilsMagnitude(temp.getInterfaceFonctionFilsMagnitude(j));
}
}
else if (n instanceof NoeudFonctionnelExogene)
vectorNoeudExogene.addNoeudFonctionnel((NoeudFonctionnelExogene)n);
}
// parametres divers
h2 = 3; // Squared divided-difference step size
h = Math.sqrt(h2); // Divided difference step-size
scal1 = 0.5/h; // A convenient scaling factor
scal2 = Math.sqrt((h2-1)/(4*h2*h2));// Another scaling factor
// variables de dimension
nu = vectorNoeudExogene.size();
nxA = vectorNoeudEndogeneActivation.size();
nxE = vectorNoeudEndogeneEmission.size();
nyA = vectorNoeudObserveActivation.size();
nyE = vectorNoeudObserveEmission.size();
nvA = vectorBruitTraitementActivation.size();
nvE = vectorBruitTraitementEmission.size();
nwA = vectorBruitMesureActivation.size();
nwE = vectorBruitMesureEmission.size();
// matrices initiales
Matrix p0,x0;
p0 = new Matrix(nxA+nxE,nxA+nxE,0);
x0 = new Matrix(nxA+nxE,1,0);
for (int i=0;i<nxA;i++)
{ Magnitude mag = ((NoeudFonctionnelEndogene)vectorNoeudEndogeneActivation.getNoeudFonctionnel(i)).getMagnitudeActivation(0);
p0.set(i,i,mag.getEcartType());
x0.set(i,0,mag.getMoyenne());
}
for (int i=0;i<nxE;i++)
{ Magnitude mag = ((NoeudFonctionnelEndogene)vectorNoeudEndogeneEmission.getNoeudFonctionnel(i)).getMagnitudeEmission(0);
p0.set(i+nxA,i+nxA,mag.getEcartType());
x0.set(i+nxA,0,mag.getMoyenne());
}
xbar = x0;
Matrix q;
q = new Matrix(nvA+nvE,nvA+nvE,0);
for (int i=0;i<nvA;i++)
q.set(i,i,((MagnitudeBruit)vectorBruitTraitementActivation.getInterfaceFonctionFilsMagnitude(i)).getMagnitude().getEcartType());
for (int i=0;i<nvE;i++)
q.set(i+nvA,i+nvA,((MagnitudeBruit)vectorBruitTraitementEmission.getInterfaceFonctionFilsMagnitude(i)).getMagnitude().getEcartType());
Matrix r;
r = new Matrix(nwA+nwE,nwA+nwE,0);
for (int i=0;i<nwA;i++)
r.set(i,i,((MagnitudeBruit)vectorBruitMesureActivation.getInterfaceFonctionFilsMagnitude(i)).getMagnitude().getEcartType());
for (int i=0;i<nwE;i++)
r.set(i+nwA,i+nwA,((MagnitudeBruit)vectorBruitMesureEmission.getInterfaceFonctionFilsMagnitude(i)).getMagnitude().getEcartType());
// Square root of initial state covariance
EigenvalueDecomposition eigen;
Matrix v,d;
if (p0.isEmpty())
Sxbar = new Matrix(0,0);
else
{ eigen = p0.eig();
// v et d peuvent ętre complexes
v = eigen.getV();
d = diagonaliser(eigen.getD());
// le fait de diagonaliser permet de ne garder que les parties réelles
// car les éventuelles parties imaginaires ne sont pas sur la diagonale
// (cf la doc du package des Matrix)
Sxbar = triag(v.times(sqrtElmt(d)));
}
// Square root of process noise covariance
if (q.isEmpty())
Sxbar = new Matrix(0,0);
else
{ eigen = q.eig();
v = eigen.getV();
d = diagonaliser(eigen.getD());
Matrix sv = v.times(sqrtElmt(d));
hSv = sv.times(h);
}
// Square root of measurement noise cov.
if (r.isEmpty())
Sxbar = new Matrix(0,0);
else
{ eigen = r.eig();
v = eigen.getV();
d = diagonaliser(eigen.getD());
Matrix sw = v.times(sqrtElmt(d));
hSw = sw.times(h);
}
// Allocate compund matrix consisting of Sxx and Syv
SxxSxv = new Matrix(nxA+nxE,2*(nxA+nxE+nvA+nvE));
// Allocate compund matrix consisting of Syx and Syw
SyxSyw = new Matrix(nyA+nyE,2*(nxA+nxE+nwA+nwE));
// Matrix for storing state estimates
// Matrix xhat_data = new Matrix(samples+1,nxA+nxE);
// pas besoin : stocké directement dans les noeuds
// Matrix for storing cov. matrices
Smat = new Matrix(1,(int)(0.5*(nxA+nxE)*(nxA+nxE+1)));
// Index to elem. in Sx
//[I,J] = find(triu(reshape(1:nx*nx,nx,nx))');
Matrix temp = new Matrix(nxA+nxE,nxA+nxE);
for (int i=0;i<(nxA+nxE);i++)
for (int j=0;j<(nxA+nxE);j++)
temp.set(i,j,j*(nxA+nxE)+i+1);
temp = triu(temp);
temp = temp.transpose();
Matrix temp2[] = find(temp);
Matrix mI = temp2[0];
Matrix mJ = temp2[1];
// sidx = sub2ind([nx nx],J,I);
sidx = sub2ind(nxA+nxE,nxA+nxE,mJ,mI);
// Index into y-vector
// int yidx = 1;
// Mean of process noise
vmean = new Matrix(nvA+nvE,1);
// Mean of measurement noise
wmean = new Matrix(nwA+nwE,1);
// ----- Initialize state+output equations and linearization -----
nxnv2 = nxA+nxE+nvA+nvE;
nxnw2 = nxA+nxE+nwA+nwE;
// Index to location of Sxv2 and Syw2 in SxxSxv and SyxSyw matrices
idx_syw2 = 2*(nxA+nxE)+nwA+nwE-1;
idx_sxv2 = 2*(nxA+nxE)+nvA+nwE-1;
SxxSxv = acollerDroite(SxxSxv, new Matrix(nxA+nxE,nxnv2));
SyxSyw = acollerDroite(SyxSyw, new Matrix(nyA+nyE,nxnw2));
fireTraitementRaffr(new TraitementEvent(this));
}
/*
*
*/
public void evaluer(int instant) throws IOException, ClassNotFoundException, ContenuFichierIncompatibleException
{ // algo général :
// 1) mŕj Types et Magnitude d'émission des NoeudExogenes
// 2) mŕj Types d'activation des NoeudEndogenes
// 3) mŕj simultanée des Magnitudes d'activation et d'émission des NoeudEndogenes
// 4) mŕj Types d'émission des NoeudEndogenes
// 5) mŕj TPT (apprentissage) des NoeudEndogenes
// ------------------------------------------------------
// 1) mŕj Types et Magnitude d'émission des NoeudExogenes
// ------------------------------------------------------
for (int i=0;i<nu;i++)
{ NoeudFonctionnelExogene n = (NoeudFonctionnelExogene)vectorNoeudExogene.getNoeudFonctionnel(i);
if (instant != 0)
{ Vector resultat;
resultat = n.lireEntreeFichier();
// Magnitude
Magnitude resM = (Magnitude) resultat.get(0);
n.addMagnitudeEmission(resM);
// Type
Type resT = (Type) resultat.get(1);
try
{ n.addTypeEmission(resT);
}
catch (DomaineIncompatibleException e)
{ e.printStackTrace();
}
}
}
// ------------------------------------------------------
// 2) mŕj Types d'activation des NoeudEndogenes
// ------------------------------------------------------
// non-observables
try
{ for (int i=0;i<nxA;i++)
{ NoeudFonctionnelEndogene n = (NoeudFonctionnelEndogene)vectorNoeudEndogeneActivation.getNoeudFonctionnel(i);
// Type d'activation
Type resT = n.getSectionActivation().getFonctionType().evaluer(instant);
n.addTypeActivation(resT);
// mise ŕ jour des variables persistantes du Noeud
n.getSectionApprentissage().getFonctionTPT().raffraichirNoeud(instant);
}
// observables (aucune différence en ce qui concerne les Types)
for (int i=0;i<nyA;i++)
{ NoeudFonctionnelEndogene n = (NoeudFonctionnelEndogene)vectorNoeudObserveActivation.getNoeudFonctionnel(i);
// Type d'activation
Type resT = n.getSectionActivation().getFonctionType().evaluer(instant);
n.addTypeActivation(resT);
// mise ŕ jour des variables persistantes du Noeud
n.getSectionApprentissage().getFonctionTPT().raffraichirNoeud(instant);
}
}
catch (DomaineIncompatibleException e)
{ e.printStackTrace();
}
// ------------------------------------------------------
// 3) mŕj simultanée des Magnitudes d'activation et d'émission des NoeudEndogenes
// ------------------------------------------------------
// d'aprčs le script Matlab de Magnus Norgaard
Matrix fxbar, sxp, sxm, svp, svm, y0, ybar, syp, sym, swp, swm, Sy, K, y;
int kx2;
// --- Time update (a'priori update) of state and covariance ---
if (instant!=1)
{ // etat(instant-1) = xhat, bruit = vmean
fxbar = fevalX(instant);
xbar = fxbar.times((h2-nxnv2)/h2);
kx2 = nxA+nxE+nvA+nvE;
for (int kx=0;kx<nxA+nxE;kx++)
{ // etat(instant-1) = xhat+h*Sx(:,kx), bruit = vmean
changerEtat(instant-1,xhat.plus(Sx.getMatrix(0,Sx.getRowDimension()-1,kx,kx).times(h)));
sxp = fevalX(instant);
// etat(instant-1) = xhat-h*Sx(:,kx), bruit = vmean
changerEtat(instant-1,xhat.minus(Sx.getMatrix(0,Sx.getRowDimension()-1,kx,kx).times(h)));
sxm = fevalX(instant);
// SxxSxv(:,kx) = scal1*(sxp-sxm);
SxxSxv.setMatrix(0,SxxSxv.getRowDimension()-1,kx,kx,sxp.minus(sxm).times(scal1));
// SxxSxv(:,kx2+kx) = scal2*(sxp+sxm-2*fxbar);
SxxSxv.setMatrix(0,SxxSxv.getRowDimension()-1,kx2+kx-1,kx2+kx-1,sxp.plus(sxm).minus(fxbar.times(2)).times(scal2));
// xbar = xbar + (sxp+sxm)/(2*h2);
xbar = xbar.plus(sxp.plus(sxm).times(1/(2*h2)));
}
changerEtat(instant-1,xhat);
for (int kv=0;kv<nvA+nvE;kv++)
{ // etat(instant-1) = xhat, bruit = hSv(:,kv)
changerBruitTraitement(hSv.getMatrix(0,hSv.getRowDimension()-1,kv,kv));
svp = fevalX(instant);
// etat(instant-1) = xhat, bruit = -hSv(:,kv)
changerBruitTraitement(hSv.getMatrix(0,hSv.getRowDimension()-1,kv,kv).times(-1));
svm = fevalX(instant);
// SxxSxv(:,nx+kv) = scal1*(svp-svm);
SxxSxv.setMatrix(0,SxxSxv.getRowDimension()-1,nxA+nxE+kv-1,nxA+nxE+kv-1,svp.minus(svm).times(scal1));
// SxxSxv(:,idx_sxv2+kv) = scal2*(svp+svm-2*fxbar);
SxxSxv.setMatrix(0,SxxSxv.getRowDimension()-1,idx_sxv2+kv-1,idx_sxv2+kv-1,(svp.plus(svm).minus(fxbar.times(2))).times(scal2));
// xbar = xbar + (svp+svm)/(2*h2);
xbar = xbar.plus(svp.plus(svm).times(1/(2*h2)));
}
// Cholesky factor of a'priori estimation error covariance
Sxbar = triag(SxxSxv);
}
// --- Measurement update (a posteriori update) ---
// etat(instant) = xbar, bruit = wmean
creerEtat(xbar);
changerBruitMesure(wmean);
y0 = fevalY(instant);
if (estObservable(instant))
{ ybar = y0.times((h2-nxnw2)/h2);
kx2 = nxA+nxE+nwA+nwE;
for (int kx=0;kx<nxA+nxE;kx++)
{ // etat(instant) = xbar+h*Sxbar(:,kx), bruit = wmean
changerEtat(instant,xbar.plus(Sxbar.getMatrix(0,Sxbar.getRowDimension()-1,kx,kx).times(h)));
syp = fevalY(instant);
// etat(instant) = xbar-h*Sxbar(:,kx), bruit = wmean
changerEtat(instant,xbar.minus(Sxbar.getMatrix(0,Sxbar.getRowDimension()-1,kx,kx).times(h)));
sym = fevalY(instant);
// SyxSyw(:,kx) = scal1*(syp-sym);
SyxSyw.setMatrix(0,SyxSyw.getRowDimension()-1,kx,kx,syp.minus(sym).times(scal1));
// SyxSyw(:,kx2+kx) = scal2*(syp+sym-2*y0);
SyxSyw.setMatrix(0,SyxSyw.getRowDimension()-1,kx2+kx-1,kx2+kx-1,syp.plus(sym).minus(y0.times(2)).times(scal2));
// ybar = ybar + (syp+sym)/(2*h2);
ybar = ybar.plus(syp.plus(sym).times(1/(2*h2)));
}
changerEtat(instant,xbar);
for (int kw=0;kw<nwA+nwE;kw++)
{ // etat(instant) = xbar, bruit = hSw(:,kw)
changerBruitMesure(hSw.getMatrix(0,hSw.getRowDimension()-1,kw,kw));
swp = fevalY(instant);
// etat(instant) = xbar, bruit = -hSw(:,kw)
changerBruitMesure(hSw.getMatrix(0,hSw.getRowDimension()-1,kw,kw).times(-1));
swm = fevalY(instant);
// SyxSyw(:,nx+kw) = scal1*(swp-swm);
SyxSyw.setMatrix(0,SyxSyw.getRowDimension()-1,nxA+nxE+kw-1,nxA+nxE+kw-1,swp.minus(swm).times(scal1));
// SyxSyw(:,idx_syw2+kw) = scal2*(swp+swm-2*y0);
SyxSyw.setMatrix(0,SyxSyw.getRowDimension()-1,idx_syw2+kw,idx_syw2+kw,swp.plus(swm).minus(y0.times(2)).times(scal2));
// ybar = ybar + (swp+swm)/(2*h2);
ybar = ybar.plus(swp.plus(swm).times(1/(2*h2)));
}
// Cholesky factor of a'posteriori output estimation error covariance
Sy = triag(SyxSyw);
// K = (Sxbar*SyxSyw(:,1:nx)')/(Sy*Sy');
K = Sxbar.times(SyxSyw.getMatrix(0,SyxSyw.getRowDimension()-1,0,nxA+nxE-1).transpose()).times(Sy.times(Sy.transpose()).inverse());
// State estimate
y = getObservations(instant);
// xhat = xbar + K*(y(yidx,:)'-ybar);
xhat = xbar.plus(K.times(y.minus(ybar)));
// Cholesky factor of a'posteriori estimation error covariance
// Sx = triag([Sxbar-K*SyxSyw(:,1:nx) K*SyxSyw(:,nx+1:end)]);
Sx = triag(acollerDroite(Sxbar.minus(K.times(SyxSyw.getMatrix(0,SyxSyw.getRowDimension()-1,0,nxA+nxE-1))),K.times(SyxSyw.getMatrix(0,SyxSyw.getRowDimension()-1,nxA+nxE+1-1,SyxSyw.getColumnDimension()-1))));
//yidx = yidx + 1;
}
// No observations available at this sampling instant
else
{ // Copy a priori state estimate
xhat = xbar;
// Copy a priori covariance factor
Sx = Sxbar;
//
y = y0;
}
// --- Store results ---
// xhat_data(k,:) = xhat';
// extraire(vecteur) permet d'extraire un vecteur contenant les valeurs
// de la matrice aux coordonnées spécifiées ds le vecteur d'entrée
// Smat(k,:) = Sx(sidx)';
// NOTE ici je considčre que les valeurs de l'instant 0 sont dans la matrice
// Smat.setMatrix(instant,instant,0,Smat.getColumnDimension()-1,extraire(Sx,sidx.transpose()));
Smat = acollerBas(Smat,extraire(Sx,sidx).transpose());
// stocker les moyennes ds les historiques des Noeuds
changerEtat(instant,xhat);
changerObservation(instant, y);
// ------------------------------------------------------
// 4) mŕj Types d'émission des NoeudEndogenes
// ------------------------------------------------------
// non-observables
try
{ for (int i=0;i<nxE;i++)
{ NoeudFonctionnelEndogene n = (NoeudFonctionnelEndogene)vectorNoeudEndogeneEmission.getNoeudFonctionnel(i);
Type resT = n.getSectionEmission().getFonctionType().evaluer(instant);
n.addTypeEmission(resT);
}
// observables (aucune différence en ce qui concerne les Types)
for (int i=0;i<nyE;i++)
{ NoeudFonctionnelEndogene n = (NoeudFonctionnelEndogene)vectorNoeudObserveEmission.getNoeudFonctionnel(i);
Type resT = n.getSectionEmission().getFonctionType().evaluer(instant);
n.addTypeEmission(resT);
}
}
catch (DomaineIncompatibleException e)
{ e.printStackTrace();
}
// ------------------------------------------------------
// 5) mŕj TPT (apprentissage) des NoeudEndogenes
// ------------------------------------------------------
// non-observables
try
{ for (int i=0;i<nxE;i++)
{ NoeudFonctionnelEndogene n = (NoeudFonctionnelEndogene)vectorNoeudEndogeneEmission.getNoeudFonctionnel(i);
TPT res = n.getSectionApprentissage().getFonctionTPT().evaluer(instant);
n.addTPT(res);
}
// observables (aucune différence en ce qui concerne les Types)
for (int i=0;i<nyE;i++)
{ NoeudFonctionnelEndogene n = (NoeudFonctionnelEndogene)vectorNoeudObserveEmission.getNoeudFonctionnel(i);
TPT res = n.getSectionApprentissage().getFonctionTPT().evaluer(instant);
n.addTPT(res);
}
}
catch (DomaineIncompatibleException e)
{ e.printStackTrace();
}
}
/*
*
*/
public void interrompreSimulation()
{ // on efface les variables qui ont servi lors de la simulation
hSv = null;
hSw = null;
sidx = null;
Smat = null;
Sx = null;
Sxbar = null;
SxxSxv = null;
SyxSyw = null;
vectorBruitMesureActivation = null;
vectorBruitMesureEmission = null;
vectorBruitTraitementActivation = null;
vectorBruitTraitementEmission = null;
vectorNoeudEndogeneActivation = null;
vectorNoeudEndogeneEmission = null;
vectorNoeudExogene = null;
vectorNoeudObserveActivation = null;
vectorNoeudObserveEmission = null;
vmean = null;
wmean = null;
xbar = null;
xhat = null;
}
/*
*
*/
public void terminerSimulation()
{ // SMAT2VAR(Smat) returns a matrix where each column is the variance
// of a state estimate.
Matrix var = smat2var(Smat);
for (int i=0;i<var.getRowDimension();i++)
{ for (int j=0;j<nxA;j++)
// NOTE : vérif' le i+1. ça dépend si l'instant 0 est stocké ou pas dans la matrice des instants. suffit de vérifier dans la matrice des états
((NoeudFonctionnelEndogene) vectorNoeudEndogeneActivation.getNoeudFonctionnel(j)).getMagnitudeActivation(i+1).setEcartType(var.get(i,j));
for (int j=0;j<nxE;j++)
// NOTE : vérif' ausi le i+1
((NoeudFonctionnelEndogene) vectorNoeudEndogeneEmission.getNoeudFonctionnel(j)).getMagnitudeEmission(i+1).setEcartType(var.get(i,j+nxA));
}
// on efface les variables qui ont servi lors de la simulation
hSv = null;
hSw = null;
sidx = null;
Smat = null;
Sx = null;
Sxbar = null;
SxxSxv = null;
SyxSyw = null;
vectorBruitMesureActivation = null;
vectorBruitMesureEmission = null;
vectorBruitTraitementActivation = null;
vectorBruitTraitementEmission = null;
vectorNoeudEndogeneActivation = null;
vectorNoeudEndogeneEmission = null;
vectorNoeudExogene = null;
vectorNoeudObserveActivation = null;
vectorNoeudObserveEmission = null;
vmean = null;
wmean = null;
xbar = null;
xhat = null;
}
//----------------------------------------
// Fonctions d'évaluation
//----------------------------------------
/**
* réalise l'évaluation des états ŕ un instant donné.
*
* @param instant instant de l'évaluation ŕ réaliser.
* @return une matrice (vecteur) contenant le résultat de l'évaluation.
*/
private Matrix fevalX(int instant)
{ Matrix resultat = new Matrix(nxA+nxE,1);
for (int i=0;i<nxA;i++)
{ NoeudFonctionnelEndogene n = (NoeudFonctionnelEndogene)vectorNoeudEndogeneActivation.getNoeudFonctionnel(i);
Magnitude resM = n.getSectionActivation().getFonctionMagnitude().evaluer(instant);
n.setMagnitudeActivation(instant,resM);
resultat.set(i,0,resM.getMoyenne());
}
for (int i=0;i<nxE;i++)
{ NoeudFonctionnelEndogene n = (NoeudFonctionnelEndogene)vectorNoeudEndogeneEmission.getNoeudFonctionnel(i);
Magnitude resM = n.getSectionEmission().getFonctionMagnitude().evaluer(instant);
n.setMagnitudeEmission(instant,resM);
resultat.set(i+nxA,0,resM.getMoyenne());
}
return resultat;
}
/**
* réalise l'évaluation des observations ŕ un instant donné.
*
* @param instant instant de l'évaluation ŕ réaliser.
* @return une matrice (vecteur) contenant le résultat de l'évaluation.
*/
private Matrix fevalY(int instant)
{ Matrix resultat = new Matrix(nyA+nyE,1);
for (int i=0;i<nyA;i++)
{ NoeudFonctionnelEndogene n = (NoeudFonctionnelEndogene)vectorNoeudObserveActivation.getNoeudFonctionnel(i);
Magnitude resM = n.getSectionActivation().getFonctionMagnitude().evaluer(instant);
resultat.set(i,0,resM.getMoyenne());
}
for (int i=0;i<nyE;i++)
{ NoeudFonctionnelEndogene n = (NoeudFonctionnelEndogene)vectorNoeudObserveEmission.getNoeudFonctionnel(i);
Magnitude resM = n.getSectionEmission().getFonctionMagnitude().evaluer(instant);
resultat.set(i+nyA,0,resM.getMoyenne());
}
return resultat;
}
//----------------------------------------
// Manipulation des États/Bruits
//----------------------------------------
/**
* insčre la Magnitude définissant un nouvel instant, pour chaque noeud.
*
* @param m matrice contenant les nouveaux états.
*/
private void creerEtat(Matrix m)
{ int index = 0;
for (int i=0;i<nxA;i++)
{ NoeudFonctionnelEndogene noeud = (NoeudFonctionnelEndogene)vectorNoeudEndogeneActivation.getNoeudFonctionnel(i);
Magnitude magnitude = new Magnitude(noeud.getSectionActivation());
magnitude.setMoyenne(m.get(index,0));
noeud.addMagnitudeActivation(magnitude);
index ++;
}
for (int i=0;i<nxE;i++)
{ NoeudFonctionnelEndogene noeud = (NoeudFonctionnelEndogene)vectorNoeudEndogeneEmission.getNoeudFonctionnel(i);
Magnitude magnitude = new Magnitude(noeud.getSectionEmission());
magnitude.setMoyenne(m.get(index,0));
noeud.addMagnitudeEmission(magnitude);
index ++;
}
}
/**
* échange les états de l'instant passé en paramčtre par
* ceux contenus dans la matrice.
*
* @param instant instant des états ŕ échanger.
* @param m matrice contenant les nouveaux états.
*/
private void changerEtat(int instant, Matrix m)
{ int index = 0;
for (int i=0;i<nxA;i++)
{ ((NoeudFonctionnelEndogene) vectorNoeudEndogeneActivation.getNoeudFonctionnel(i)).getMagnitudeActivation(instant).setMoyenne(m.get(index,0));
index ++;
}
for (int i=0;i<nxE;i++)
{ ((NoeudFonctionnelEndogene) vectorNoeudEndogeneEmission.getNoeudFonctionnel(i)).getMagnitudeEmission(instant).setMoyenne(m.get(index,0));
index ++;
}
}
/**
* échange les observations de l'instant passé en paramčtre par
* celles contenues dans la matrice.
*
* @param instant instant des observations ŕ échanger.
* @param m matrice contenant les nouvelles observations.
*/
private void changerObservation(int instant, Matrix m)
{ int index = 0;
for (int i=0;i<nyA;i++)
{ ((NoeudFonctionnelEndogene) vectorNoeudObserveActivation.getNoeudFonctionnel(i)).getMagnitudeActivation(instant).setMoyenne(m.get(index,0));
index ++;
}
for (int i=0;i<nyE;i++)
{ ((NoeudFonctionnelEndogene) vectorNoeudObserveEmission.getNoeudFonctionnel(i)).getMagnitudeEmission(instant).setMoyenne(m.get(index,0));
index ++;
}
}
/**
* échange les bruits de traitement par ceux contenus dans la matrice.
*
* @param m matrice contenant les nouveaux bruits de traitement.
*/
private void changerBruitTraitement(Matrix m)
{ int index = 0;
for (int i=0;i<nvA;i++)
{ ((MagnitudeBruit) vectorBruitTraitementActivation.getInterfaceFonctionFilsMagnitude(i)).getMagnitude().setMoyenne(m.get(index,0));
index ++;
}
for (int i=0;i<nvE;i++)
{ ((MagnitudeBruit) vectorBruitTraitementEmission.getInterfaceFonctionFilsMagnitude(i)).getMagnitude().setMoyenne(m.get(index,0));
index ++;
}
}
/**
* échange les bruits de mesure par ceux contenus dans la matrice.
*
* @param m matrice contenant les nouveaux bruits de mesure.
*/
private void changerBruitMesure(Matrix m)
{ int index = 0;
for (int i=0;i<nwA;i++)
{ ((MagnitudeBruit) vectorBruitMesureActivation.getInterfaceFonctionFilsMagnitude(i)).getMagnitude().setMoyenne(m.get(index,0));
index ++;
}
for (int i=0;i<nwE;i++)
{ ((MagnitudeBruit) vectorBruitMesureEmission.getInterfaceFonctionFilsMagnitude(i)).getMagnitude().setMoyenne(m.get(index,0));
index ++;
}
}
//----------------------------------------
// Observations
//----------------------------------------
/**
* détermine si tous les Noeuds observables le sont bien ŕ
* l'instant passé en paramčtre.
*
* @param instant instant ŕ tester.
* @return vrai si tous les Noeuds observables le sont ŕ cet instant, faux sinon.
* @throws IOException si une erreur se produit lors de l'accčs au fichier.
* @throws ClassNotFoundException si une erreur se produit lors de l'accčs au fichier.
*/
private boolean estObservable(int instant) throws IOException, ClassNotFoundException
{ boolean resultat = true;
for (int i=0;i<nyA;i++)
resultat = resultat && ((NoeudFonctionnelEndogene) vectorNoeudObserveActivation.getNoeudFonctionnel(i)).estObservableActivation(instant);
for (int i=0;i<nyE;i++)
resultat = resultat && ((NoeudFonctionnelEndogene) vectorNoeudObserveEmission.getNoeudFonctionnel(i)).estObservableEmission(instant);
return resultat;
}
/**
* renvoie la matrice (vecteur) des valeurs observées
* ŕ l'instant passé en paramčtre.
*
* @param instant pour lequel on veut les observations.
* @return observations ŕ l'instant donné.
* @throws IOException si une erreur se produit lors de l'accčs au fichier.
* @throws ClassNotFoundException si une erreur se produit lors de l'accčs au fichier.
*/
private Matrix getObservations(int instant) throws IOException, ClassNotFoundException
{ Matrix resultat = new Matrix(nyA+nyE,1);
for (int i=0;i<nyA;i++)
{ NoeudFonctionnelEndogene noeud = ((NoeudFonctionnelEndogene)vectorNoeudObserveActivation.getNoeudFonctionnel(i));
Magnitude magnitude = noeud.getObservationActivationValeur(instant);
noeud.setMagnitudeActivation(instant, magnitude);
resultat.set(i,0,magnitude.getMoyenne());
}
for (int i=0;i<nyE;i++)
{ NoeudFonctionnelEndogene noeud = ((NoeudFonctionnelEndogene)vectorNoeudObserveEmission.getNoeudFonctionnel(i));
Magnitude magnitude = noeud.getObservationEmissionValeur(instant);
noeud.setMagnitudeEmission(instant, magnitude);
resultat.set(i+nyA,0,magnitude.getMoyenne());
}
return resultat;
}
//----------------------------------------
// Manipulation des Matrix
// Méthodes adaptées de Norgaard
//----------------------------------------
// NOTE possibilité de bug du ŕ l'apparition de valeurs complexes, cf appel de cette méthode
/**
* méthode adaptée de celle de Magnus Norgaard.
* <p>
* S=triag(A) uses a Householder transformation of the rectangular
* matrix A to produce a square and upper triangular matrix S with
* the property S*S' = A*A'.
*<p>
* Literature:
* The algorithm is described in Grewal & Andrews: "Kalman Filtering -
* Theory and Practice" Prentice-Hall, 1993, pp. 234. However, there
* are certain cases in which their implementation fails. These have been
* handled as described in G.W. Stewart: "Matrix Algorithms,
* Vol. 1: Basic Decompositions", SIAM 1988.
*<p>
* Written by: Magnus Norgaard, IMM/IAU, Technical University of Denmark
* LastEditDate: Apr. 15, 2000
*
*
*
* @param m la matrice rectangulaire que l'on veut triangulariser.
* @return la matrice triangulaire.
*/
private Matrix triag(Matrix m)
{ Matrix a = m.copy();
// Rows and columns of A
// [n,rn]=size(A);
int n = a.getRowDimension();
int rn = a.getColumnDimension();
// r = rn-n;
int r = rn-n;
double ny;
// v = zeros(n,1);
Matrix v = new Matrix(n,1);
// u = zeros(1,rn);
Matrix u = new Matrix(1,rn);
// S = zeros(n,n);
Matrix S = new Matrix(n,n);
// for k=n:-1:1,
for (int k=(n-1);k>=0;k--)
{ // u(1:r+k) = A(k,1:r+k);
u.setMatrix(0,0,0,r+k,a.getMatrix(k,k,0,r+k));
// ny = norm(u(1:r+k));
ny = u.getMatrix(0,0,0,r+k).normF();
// if ny==0,
if (ny==0)
// u(r+k) = sqrt(2);
u.set(0,r+k,Math.sqrt(2));
// else
else
{ // u(1:r+k) = u(1:r+k)/ny;
u.setMatrix(0,0,0,r+k,u.getMatrix(0,0,0,r+k).times(1/ny));
// if u(r+k)>=0,
if (u.get(0,r+k)>=0)
{ // u(r+k) = u(r+k) + 1;
u.set(0,r+k,u.get(0,r+k)+1);
// ny = -ny;
ny = -ny;
}
// else
else
// u(r+k) = u(r+k) - 1;
u.set(0,r+k,u.get(0,r+k)-1);
//u(1:r+k) = u(1:r+k)/sqrt(abs(u(r+k)));
u.setMatrix(0,0,0,r+k,u.getMatrix(0,0,0,r+k).times(1/Math.sqrt(Math.abs(u.get(0,r+k)))));
}
//v(1:k-1,1) = A(1:k-1,1:r+k)*u(1,1:r+k)';
v.setMatrix(0,k-1,0,0,a.getMatrix(0,k-1,0,r+k).times(u.getMatrix(0,0,0,r+k).transpose()));
//A(1:k-1,1:r+k) = A(1:k-1,1:r+k) - v(1:k-1,1)*u(1,1:r+k);
a.setMatrix(0,k-1,0,r+k,a.getMatrix(0,k-1,0,r+k).minus(v.getMatrix(0,k-1,0,0).times(u.getMatrix(0,0,0,r+k))));
//S(1:k-1,k) = A(1:k-1,r+k);
S.setMatrix(0,k-1,k,k,a.getMatrix(0,k-1,r+k,r+k));
//S(k,k)=ny;
S.set(k,k,ny);
}
return S;
}
/**
* équivalent ŕ la fonction smat2cov de Norgaard qui permet de passer
* d'une matrice triangularisée aux variances.
* <p>
* SMAT2VAR Calculate variance estimate for each state.
* SMAT2VAR(Smat) returns a matrix where each column is the variance
* of a state estimate. 'Smat' is a matrix where each row contains elements
* of (the upper triangular part of) the Cholesky factor of a covariance
* matrix.
*
* @param sMat matrice triangulaire.
* @return matrice de covariance.
*/
private Matrix smat2var(Matrix sMat)
{ // Number of states
// states = round(-0.5 + sqrt(0.25 + 2*size(sMat,2)));
int states = (int) Math.round(-0.5 + Math.sqrt(0.25 + 2*sMat.getColumnDimension()));
// Index to first element in each row
// idx = cumsum ([1 states:-1:2]);
Matrix idx = new Matrix(1,states);
idx.set(0,0,1);
for (int i=1;i<states;i++)
idx.set(0,i,states+1-i);
for (int i=1;i<states;i++)
idx.set(0,i,idx.get(0,i-1)+idx.get(0,i));
// Index to last element in each row
//idx2 = idx+[states-1:-1:0];
Matrix temp = new Matrix(1,states);
for (int i=0;i<states;i++)
temp.set(0,i,states-1-i);
Matrix idx2 = idx.plus(temp);
// Allocate space for variance matrix
// vars = zeros(size(sMat,1),states);
Matrix vars = new Matrix(sMat.getRowDimension(),states);
// for k=1:states,
// vars(:,k) = sum(Smat(:,idx(k):idx2(k)).*Smat(:,idx(k):idx2(k)),2);
// end
for (int k=0;k<states;k++)
{ // Smat(:,idx(k):idx2(k))
Matrix temp2 = sMat.getMatrix(0,sMat.getRowDimension()-1,(int)idx.get(0,k)-1,(int)idx2.get(0,k)-1);
// Smat(:,idx(k):idx2(k)).*Smat(:,idx(k):idx2(k))
temp2 = temp2.arrayTimes(sMat.getMatrix(0,sMat.getRowDimension()-1,(int)idx.get(0,k)-1,(int)idx2.get(0,k)-1));
// sum(Smat(:,idx(k):idx2(k)).*Smat(:,idx(k):idx2(k)),2);
Matrix temp3 = new Matrix(sMat.getRowDimension(),1);
for (int i=0;i<temp2.getRowDimension();i++)
for (int j=0;j<temp2.getColumnDimension();j++)
temp3.set(i,0,temp3.get(i,0)+temp2.get(i,j));
// vars(:,k) = sum(Smat(:,idx(k):idx2(k)).*Smat(:,idx(k):idx2(k)),2);
vars.setMatrix(0,sMat.getRowDimension()-1,k,k,temp3);
}
return vars;
}
//----------------------------------------
// Manipulation des Matrix
// Méthodes adaptées de Matlab
//----------------------------------------
/**
* équivalent de la fonction 'find' de Matlab.
* <p>
* FIND Find indices of nonzero elements.
* [I,J] = FIND(X) returns the row and column indices of
* the nonzero entries in the matrix X. This is often used
* with sparse matrices.
* <p>
* rque : version simplifiée par rapport ŕ celle de matlab, puisque
* je ne prends qu'un seul paramčtre : la matrice ŕ traiter. De plus,
* il y a aussi une restriction au niveau de ce qui est renvoyé, puisque
* il s'agit seulement de coordonnées classique (pas les coordonnées linéaires
* ou les valeurs qui sont non-nulles).
*
* @param a la matrice ŕ tester.
* @return renvoie un tableau de 2 matrices (vecteurs) contenant les
* coordonnées des éléments non nuls de la matrice passée en paramčtre.
*/
private Matrix[] find(Matrix a)
{ Matrix resultat[] = new Matrix[2];
Vector tempI = new Vector();
Vector tempJ = new Vector();
for (int i=0;i<a.getRowDimension();i++)
for (int j=0;j<a.getColumnDimension();j++)
if (a.get(i,j) != 0)
{ tempI.add(new Integer(i));
tempJ.add(new Integer(j));
}
resultat[0] = new Matrix(tempI.size(),1);
resultat[1] = new Matrix(tempI.size(),1);
for (int i=0;i<tempI.size();i++)
{ resultat[0].set(i,0,((Integer)tempI.get(i)).intValue());
resultat[1].set(i,0,((Integer)tempJ.get(i)).intValue());
}
return resultat;
}
/**
* équivalent de la fonction 'sub2ind' de Matlab.
* <p>
* SUB2IND Linear index from multiple subscripts.
* SUB2IND is used to determine the equivalent single index
* corresponding to a given set of subscript values.
* IND = SUB2IND(SIZ,I,J) returns the linear index equivalent to the
* row and column subscripts in the arrays I and J for a matrix of
* size SIZ.
* <p>
* rque : j'ai implémenté le cas particulier utilisé ici (matrice ŕ 2 dimensions), pas le cas général
* ŕ la différence de la version matlab, ici on commence la numérotation ŕ 0. Par exemple, pour une matrice
* 2x4, ça donne :
* [ 0 2 4 6
* 1 3 5 7 ]
* et non pas (en matlab) :
* [ 1 3 5 7
* 2 4 6 8 ]
*<p>
* exemple :
* [1],[1] -> [3]
* [0,1],[1,1] -> [2,3]
* [0,1],[1,1] -> [2,3]
* [0,1 ,[0,0 [0,1
* 0,1] 1,1] -> 2,3]
* etc.
*
* @param siz1 nombre de lignes de la matrice ŕ numéroter.
* @param siz2 nombre de colonnes de la matrice ŕ numéroter.
* @param mI matrice des lignes des éléments dont on veut les coordonnées.
* @param mJ matrice des colonnes des éléments dont on veut les coordonnées.
* @return la matrice de coordonnées linéaires des éléments dans la matrice de dimensions spécifiées.
*
*/
private Matrix sub2ind(int siz1, int siz2, Matrix mI, Matrix mJ)
{ Matrix resultat = new Matrix(mI.getRowDimension(),mI.getColumnDimension());
for (int i=0;i<mI.getRowDimension();i++)
for (int j=0;j<mI.getColumnDimension();j++)
resultat.set(i,j,mJ.get(i,j)*siz1+mI.get(i,j));
return resultat;
}
//----------------------------------------
// Manipulation des Matrix
// Méthodes basiques
//----------------------------------------
/**
* renvoie la partie réelle de la racine carrée de chaque élément
* de la matrice passée en paramčtre.
*
* @param a matrice dont on veut les racines carrées.
* @return la matrice contenant les racines carrées.
*/
private Matrix sqrtElmt(Matrix a)
{ Matrix resultat = new Matrix(a.getRowDimension(), a.getColumnDimension());
for(int i=0;i<a.getRowDimension();i++)
for(int j=0;j<a.getColumnDimension();j++)
{ double valeur = a.get(i,j);
if (valeur>=0)
resultat.set(i,j,Math.sqrt(valeur));
else
// si le nbre est négatif, la partie réelle
// de la racine carrée (complexe) est toujours 0
resultat.set(i,j,0);
}
return resultat;
}
//
/**
* renvoie la partie triangulaire supérieure d'une matrice
* sous la forme d'une nouvelle matrice
*
* @param a la matrice originale.
* @return la partie triangulaire supérieure de la matrice 'a'.
*/
private Matrix triu(Matrix a)
{ Matrix resultat = a.copy();
for (int i=0;i<a.getRowDimension();i++)
for (int j=0;j<a.getColumnDimension();j++)
if (i>j)
resultat.set(i,j,0);
return resultat;
}
/**
* accolle la seconde matrice ŕ gauche de la premiere.
* Leurs dimensions doivent ętre compatibles
*
* @param a permičre matrice ŕ accoller.
* @param b seconde matrice ŕ accoller.
* @return matrice résultant de l'accollage.
*/
private Matrix acollerDroite(Matrix a, Matrix b)
{ Matrix resultat = new Matrix(a.getRowDimension(), a.getColumnDimension()+b.getColumnDimension());
for (int i=0;i<a.getRowDimension();i++)
for (int j=0;j<a.getColumnDimension();j++)
resultat.set(i,j,a.get(i,j));
for (int i=0;i<b.getRowDimension();i++)
for (int j=0;j<b.getColumnDimension();j++)
resultat.set(i,a.getColumnDimension()+j,b.get(i,j));
return resultat;
}
/**
* accolle la seconde matrice en bas de la premiere.
* Leurs dimensions doivent ętre compatibles
*
* @param a permičre matrice ŕ accoller.
* @param b seconde matrice ŕ accoller.
* @return matrice résultant de l'accollage.
*/
private Matrix acollerBas(Matrix a, Matrix b)
{ Matrix resultat = new Matrix(a.getRowDimension()+b.getRowDimension(), a.getColumnDimension());
for (int i=0;i<a.getRowDimension();i++)
for (int j=0;j<a.getColumnDimension();j++)
resultat.set(i,j,a.get(i,j));
for (int i=0;i<b.getRowDimension();i++)
for (int j=0;j<b.getColumnDimension();j++)
resultat.set(a.getRowDimension()+i,j,b.get(i,j));
return resultat;
}
/**
* extrait un vecteur colonne contenant les valeurs de la matrice
* 'm' aux coordonnées linéaires spécifiées dans le vecteur colonne 'coord'.
* exemple :
* m = [ 1 2 3 4
* 5 6 7 8 ]
* coord = [1
* 2
* 6 ]
* resultat = [5
* 2
* 4 ]
* La matrice m est numérotée comme dans la fonction sub2ind, c'est ŕ dire :
* m = [ 0 2 4 6
* 1 3 5 7 ]
*
* @param m matrice dont on veut extraire des valeurs.
* @param coord matrice (vecteur) contenant les coordonnées linéaires dans 'm' des valeurs ŕ extraire.
* @return matrice (vecteur) contenant les valeurs extraites.
*/
private Matrix extraire(Matrix m, Matrix coord)
{ Matrix resultat = new Matrix(coord.getRowDimension(),1);
for (int i=0;i<coord.getRowDimension();i++)
{ int index = (int) coord.get(i,0);
resultat.set(i,0,m.get(index%m.getRowDimension(),index/m.getRowDimension()));
}
return resultat;
}
/**
* renvoie une matrice ne contenant que la diagonale de la matrice passée en paramčtre.
* @param m matrice dont qu'on veut diagonaliser.
* @return matrice contenant uniquement la diagonale de m, et des zéros ailleurs.
*/
public Matrix diagonaliser(Matrix m)
{ Matrix resultat = new Matrix(m.getRowDimension(),m.getColumnDimension(),0);
for (int i=0; i<m.getRowDimension(); i++)
resultat.set(i,i,m.get(i,i));
return resultat;
}
// ----------------------------------------
// Copier/Coller
// ----------------------------------------
/*
*
*/
public InterfaceMoteur cloner()
{ MoteurDD2 resultat = new MoteurDD2(parent);
resultat.setNonModifie();
return resultat;
}
/*
*
*/
public InterfaceHomonyme getHomonyme(Modele modele) throws HomonymeIntrouvableException
{ InterfaceHomonyme resultat;
if (modele == getModele())
resultat = this;
else
{ resultat = modele.getMoteur();
}
return resultat;
}
// ----------------------------------------
// InterfaceAffichable
// ----------------------------------------
/*
*
*/
public void remplacer(InterfaceAffichable ia)
{ fireTraitementRempl(new TraitementEvent(this,(MoteurDD2)ia));
}
/*
*
*/
public void cacher()
{ fireTraitementCache(new TraitementEvent(this));
}
// ----------------------------------------
// Modification
// ----------------------------------------
/*
*
*/
public void setModifie()
{ modifie = true;
}
/*
*
*/
public boolean estModifie()
{ return modifie;
}
/*
*
*/
public void setNonModifie()
{ modifie = false;
fireTraitementRaffr(new TraitementEvent(this));
}
}