714 lines
18 KiB
C++
714 lines
18 KiB
C++
|
/***************************************************************************
|
||
|
pfa.cpp
|
||
|
-------------------
|
||
|
begin : Mon 9 Dec 2002
|
||
|
copyright : (C) 2002 by Yann Esposito
|
||
|
email : esposito@cmi.univ-mrs.fr
|
||
|
***************************************************************************/
|
||
|
|
||
|
/***************************************************************************
|
||
|
* *
|
||
|
* This program is free software; you can redistribute it and/or modify *
|
||
|
* it under the terms of the GNU General Public License as published by *
|
||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||
|
* (at your option) any later version. *
|
||
|
* *
|
||
|
***************************************************************************/
|
||
|
|
||
|
/*
|
||
|
Pour les notes, voir le fichier "pfa.h".
|
||
|
See "pfa.h" file to view notes.
|
||
|
*/
|
||
|
#include "pfa.H"
|
||
|
//#include <list>
|
||
|
#include <assert.h>
|
||
|
|
||
|
// renvoi vrai si le MA est un PFA
|
||
|
RESULT
|
||
|
PFA::rend_PFA (void)
|
||
|
{
|
||
|
// on emmonde
|
||
|
MA::emmonde();
|
||
|
// renormalisation of all parameters
|
||
|
renormalise();
|
||
|
return VAL (0);
|
||
|
}
|
||
|
|
||
|
RESULT
|
||
|
PFA::becomeRandom (const int nb_etats, const int nb_lettres,
|
||
|
const int num_graphe, const float densite,
|
||
|
const float prob_init, const float prob_term,
|
||
|
const float min_trans, const float max_trans)
|
||
|
{
|
||
|
// on cree un SPFA
|
||
|
SPFA::becomeRandom (nb_etats, nb_lettres,
|
||
|
num_graphe, densite,
|
||
|
prob_init, prob_term,
|
||
|
min_trans, max_trans);
|
||
|
// puis on l'emmonde et on le renormalise.
|
||
|
return rend_PFA ();
|
||
|
}
|
||
|
|
||
|
// Cree un MA aleatoire avec un nombre maximal d'aretes
|
||
|
RESULT PFA::becomeRandomMax (const int nb_etats, const int nb_lettres,
|
||
|
const int num_graphe, const int nb_succ,
|
||
|
const int nb_init, const int nb_term,
|
||
|
const float min_trans, const float max_trans)
|
||
|
{
|
||
|
SPFA::becomeRandomMax(nb_etats, nb_lettres, num_graphe, nb_succ, nb_init, nb_term,min_trans,max_trans);
|
||
|
return rend_PFA();
|
||
|
}
|
||
|
|
||
|
|
||
|
RESULT
|
||
|
PFA::becomeRandomPrefix (const int nb_etats, const int nb_lettres,
|
||
|
const int num_graphe, const float densite, const float prob_init,
|
||
|
const float prob_term, const float min_trans,
|
||
|
const float max_trans)
|
||
|
{
|
||
|
|
||
|
// On gÈnËre un MA alÈatoire avec seulement des arÍtes positives
|
||
|
SPFA::becomeRandomPrefix (nb_etats, nb_lettres,
|
||
|
num_graphe, densite,
|
||
|
prob_init, prob_term,
|
||
|
min_trans, max_trans);
|
||
|
|
||
|
// on rend un SPFA
|
||
|
return rend_PFA ();
|
||
|
}
|
||
|
|
||
|
// Arbre prefixe
|
||
|
RESULT PFA::becomePrefixTree(Sample &S)
|
||
|
{
|
||
|
bool ispref = S.isprefixiel();
|
||
|
if (!ispref)
|
||
|
{
|
||
|
S.prefixialise();
|
||
|
}
|
||
|
|
||
|
vide(); // on vide la structure du PFA
|
||
|
Sample::const_iterator w;
|
||
|
Lettre a;
|
||
|
Word v;
|
||
|
|
||
|
Sigma=S.alphabet();
|
||
|
alph=S.dictionnaire();
|
||
|
|
||
|
map< Word, State > R;
|
||
|
w = S.begin();
|
||
|
R[w->first]=addNewState(1,0);
|
||
|
|
||
|
// on commence apres epsilon d'ou le ++w au debut du for
|
||
|
for (++w ; w != S.end() ; ++w)
|
||
|
{
|
||
|
v=w->first;
|
||
|
R[v]=addNewState(0,0);
|
||
|
a=*(v.rbegin());
|
||
|
v.erase(--v.end());
|
||
|
addTransition(R[v], a , R[w->first],(float)S[w->first]/(float)S[v]);
|
||
|
}
|
||
|
// on met ‡ jour iota et tau
|
||
|
StateSet::const_iterator e;
|
||
|
Graph::const_iterator q;
|
||
|
LettreSFunc::const_iterator x;
|
||
|
SFunc::const_iterator r;
|
||
|
float sum;
|
||
|
for (e=Q.begin() ; e != Q.end() ; ++e)
|
||
|
{
|
||
|
sum = 0;
|
||
|
q=phi.find(*e);
|
||
|
if (q != phi.end())
|
||
|
{
|
||
|
for (x=q->second.begin() ; x != q->second.end() ; ++x)
|
||
|
{
|
||
|
for (r=x->second.begin() ; r != x->second.end() ; ++r)
|
||
|
{
|
||
|
sum += r->second;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
tau[*e]=1-sum;
|
||
|
}
|
||
|
|
||
|
if (!ispref)
|
||
|
{
|
||
|
S.deprefixialise();
|
||
|
}
|
||
|
return VAL(0);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// Lissage
|
||
|
RESULT PFA::lisse (int mode, float delta)
|
||
|
{
|
||
|
if (mode == 0)
|
||
|
{ // Mode sale !!!
|
||
|
SFunc::iterator q;
|
||
|
Alphabet::const_iterator a;
|
||
|
float val;
|
||
|
State s; // le nouvel etat
|
||
|
|
||
|
if (iota.empty ())
|
||
|
{
|
||
|
s = addNewState(1,delta);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
q = iota.begin ();
|
||
|
val = q->second * delta;
|
||
|
q->second = q->second * (1 - delta);
|
||
|
s = addNewState (val, delta);
|
||
|
}
|
||
|
val = 1 - delta;
|
||
|
for (a = Sigma.begin (); a != Sigma.end (); ++a)
|
||
|
addTransition (s, *a, s, val / (Sigma.size ()));
|
||
|
|
||
|
return VAL(0);
|
||
|
}
|
||
|
else if (mode == 1)
|
||
|
{
|
||
|
cerr << "PFA::lisse(), mode " << mode << " non pris en compte"
|
||
|
<< endl;
|
||
|
return ERR (1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cerr << "PFA::lisse(), mode" << mode << " non pris en compte" << endl;
|
||
|
return ERR (0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Vraissemblance
|
||
|
float PFA::Likelihood(const Sample &S)
|
||
|
{
|
||
|
if (S.isprefixiel()) {
|
||
|
cerr << "PFA::Likelihood(const Sample &S) : S is prefixial !" << endl;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
Sample::const_iterator w;
|
||
|
float result=0;
|
||
|
// cout.precision(19);
|
||
|
for (w=S.begin() ; w != S.end() ; ++w)
|
||
|
{
|
||
|
if (isnan(plog(w->first))) {
|
||
|
cerr << "ERREUR mot : " << w->first << endl;
|
||
|
}
|
||
|
else {
|
||
|
result += plog(w->first) * w->second;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
// genere un mot ‡ l'aide du PFA.
|
||
|
RESULT
|
||
|
PFA::genere_mot (Word & w, const bool safe)
|
||
|
{
|
||
|
if (PFA_SAFE)
|
||
|
{
|
||
|
if (safe)
|
||
|
assert (isPFA ());
|
||
|
}
|
||
|
|
||
|
State jeton;
|
||
|
float alea;
|
||
|
float sum;
|
||
|
SFunc::const_iterator q;
|
||
|
LettreSFunc::const_iterator a;
|
||
|
|
||
|
// w = mot vide
|
||
|
w.clear ();
|
||
|
|
||
|
// choix de l'Ètat initial q
|
||
|
// on prend un nombre de [0,1[
|
||
|
alea = ((float) rand ()) / INT_MAX;
|
||
|
// on prend le premier etat qui fait dÈpasser le seuil
|
||
|
q = iota.begin ();
|
||
|
sum = q->second;
|
||
|
while (sum < alea)
|
||
|
{
|
||
|
sum += (++q)->second;
|
||
|
}
|
||
|
jeton = q->first; // on a fait notre choix
|
||
|
|
||
|
// Fin du choix : on commence dans l'Ètat jeton
|
||
|
// on genere le mot
|
||
|
// alea prend une valeur au hasard de [0,1[, puis tant que l'on ne s'arrete pas
|
||
|
// i.e. tant que alea > tau(jeton),
|
||
|
alea = ((float) rand ()) / INT_MAX;
|
||
|
while (alea >
|
||
|
(sum =
|
||
|
(tau.find (jeton) !=
|
||
|
tau.end ())? (tau.find (jeton)->second) : 0))
|
||
|
{
|
||
|
// on choisi une transition ‡ emprunter
|
||
|
a = (phi.find (jeton)->second).begin (); //On n'a pas besoin de faire un test sur le find !
|
||
|
while (sum < alea)
|
||
|
{
|
||
|
q = a->second.begin ();
|
||
|
while ((q != a->second.end ()) && (sum < alea))
|
||
|
{
|
||
|
if ((sum += q->second) < alea)
|
||
|
q++;
|
||
|
}
|
||
|
if (sum < alea)
|
||
|
a++;
|
||
|
}
|
||
|
// et on l'emprunte
|
||
|
jeton = q->first;
|
||
|
// on rajoute la lettre gÈnÈrÈe ‡ w
|
||
|
w += a->first;
|
||
|
//w.push_back (a->first);
|
||
|
|
||
|
// on est dans l'Ètat "jeton" et on a ajoute la lettre "a->first"
|
||
|
//puis on recommence
|
||
|
alea = ((float) rand ()) / INT_MAX;
|
||
|
}
|
||
|
return VAL (0);
|
||
|
}
|
||
|
|
||
|
|
||
|
// genere un Èchantillon de mots
|
||
|
RESULT
|
||
|
PFA::genere_echantillon (int taille, Sample & S,
|
||
|
const int num_echantillon)
|
||
|
{
|
||
|
if (isPFA()) {
|
||
|
int i;
|
||
|
Word w;
|
||
|
if (num_echantillon != 0)
|
||
|
{
|
||
|
srand (num_echantillon);
|
||
|
}
|
||
|
|
||
|
S = Sample (Sigma, alph, false);
|
||
|
for (i = 0; i < taille; i++)
|
||
|
{
|
||
|
genere_mot (w, false);
|
||
|
S.insert (w);
|
||
|
}
|
||
|
return VAL (0);
|
||
|
}
|
||
|
else {
|
||
|
return MA::genere_echantillon(taille, S, num_echantillon);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// genere un Èchantillon de mots : l'echantillon reste identique si lot est identique
|
||
|
RESULT PFA::genere_echantillon (const int taille,
|
||
|
Sample & S,
|
||
|
const char *Filename,
|
||
|
const int num_echantillon)
|
||
|
{
|
||
|
if (PFA_DEBUG)
|
||
|
{
|
||
|
if (Filename == NULL)
|
||
|
{
|
||
|
cerr << " PFA::echantillon(int taille, char *Filename) : Filename = NULL !!!" << endl;
|
||
|
}
|
||
|
}
|
||
|
genere_echantillon (taille, S, num_echantillon);
|
||
|
return S.save (Filename);
|
||
|
}
|
||
|
|
||
|
// ---------- DISTANCES ---------
|
||
|
|
||
|
// renvoie la perplexité du PFA par rapport à l'echantillon S
|
||
|
double
|
||
|
PFA::perplexite (const Sample & S) const
|
||
|
{
|
||
|
double res, sum;
|
||
|
Sample::const_iterator w;
|
||
|
|
||
|
if (isPFA()) {
|
||
|
res = sum = 0;
|
||
|
for (w = S.begin (); w != S.end (); S.next (w))
|
||
|
{
|
||
|
res += plog (w->first) * w->second;
|
||
|
sum += w->second;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
res = sum = 0;
|
||
|
for (w = S.begin (); w != S.end (); S.next (w))
|
||
|
{
|
||
|
res += log (r(w->first)) * w->second;
|
||
|
sum += w->second;
|
||
|
}
|
||
|
}
|
||
|
return -res / sum;
|
||
|
}
|
||
|
|
||
|
// renvoie la perplexitÈ du PFA par rappor ‡ l'echantillon S
|
||
|
double
|
||
|
PFA::divKL (PFA &B, const Sample & S) const
|
||
|
{
|
||
|
double res, res2, sum;
|
||
|
Sample::const_iterator w;
|
||
|
|
||
|
res = res2 = sum = 0;
|
||
|
for (w = S.begin (); w != S.end (); S.next (w))
|
||
|
{
|
||
|
res += plog (w->first) * w->second;
|
||
|
res2 += B.plog(w->first) * w->second;
|
||
|
sum += w->second;
|
||
|
}
|
||
|
return (res2 - res) / sum;
|
||
|
}
|
||
|
|
||
|
|
||
|
// renvoie la norme 2 entre ce PFA et le PTA correspondant ‡ S
|
||
|
double
|
||
|
PFA::d_2(const Sample &S) const {
|
||
|
Sample::const_iterator w;
|
||
|
double res, sum;
|
||
|
double pA, pB;
|
||
|
double taille=double(S.size());
|
||
|
|
||
|
res = sum = 0;
|
||
|
for (w = S.begin (); w != S.end (); w++)
|
||
|
{
|
||
|
if (w->second >= S.seuil)
|
||
|
{
|
||
|
pA = p (w->first);
|
||
|
pB = double(w->second)/taille;
|
||
|
res += (pA - pB) * (pA - pB) * pA;
|
||
|
sum += pA;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return sqrt (res / sum);
|
||
|
}
|
||
|
|
||
|
// renvoie la norme 2 entre ce PFA et un autre
|
||
|
double
|
||
|
PFA::d_2 (const PFA & B, const Sample & S) const
|
||
|
{
|
||
|
Sample::const_iterator w;
|
||
|
double res, sum;
|
||
|
double pA, pB;
|
||
|
|
||
|
res = sum = 0;
|
||
|
|
||
|
for (w = S.begin (); w != S.end (); w++)
|
||
|
{
|
||
|
if (w->second >= S.seuil)
|
||
|
{
|
||
|
pA = p (w->first);
|
||
|
pB = B.p (w->first);
|
||
|
res += (pA - pB) * (pA - pB) * pA;
|
||
|
sum += pA;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return sqrt (res / sum);
|
||
|
}
|
||
|
|
||
|
// renvoie la norme L1 entre ce PFA et un autre
|
||
|
double
|
||
|
PFA::L_1 (const PFA & B, const Sample & S) const
|
||
|
{
|
||
|
Sample::const_iterator w;
|
||
|
double res, sum;
|
||
|
double pA, pB;
|
||
|
|
||
|
res = sum = 0;
|
||
|
for (w = S.begin (); w != S.end (); w++)
|
||
|
{
|
||
|
if (w->second >= S.seuil)
|
||
|
{
|
||
|
pA = p (w->first);
|
||
|
pB = B.p (w->first);
|
||
|
res += (pA - pB >= 0) ? (pA - pB) * pA : (pB - pA) * pA; // |pA(w) - pB(w)|*pA(w)
|
||
|
sum += pA;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return sqrt (res / sum);
|
||
|
}
|
||
|
|
||
|
|
||
|
// renvoie la norme 2 entre ce PFA et un autre
|
||
|
double
|
||
|
PFA::d_2nlog (const PFA & B, const Sample & S) const
|
||
|
{
|
||
|
Sample::const_iterator w;
|
||
|
double res, sum;
|
||
|
double pA, pB;
|
||
|
|
||
|
res = sum = 0;
|
||
|
|
||
|
for (w = S.begin (); w != S.end (); w++)
|
||
|
{
|
||
|
if (w->second >= S.seuil)
|
||
|
{
|
||
|
pA = p_directe (w->first);
|
||
|
pB = B.p_directe (w->first);
|
||
|
res += (pA - pB) * (pA - pB) * pA;
|
||
|
sum += pA;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return sqrt (res / sum);
|
||
|
}
|
||
|
|
||
|
// renvoie la norme L1 entre ce PFA et un autre
|
||
|
double
|
||
|
PFA::L_1nlog (const PFA & B, const Sample & S) const
|
||
|
{
|
||
|
Sample::const_iterator w;
|
||
|
double res, sum;
|
||
|
double pA, pB;
|
||
|
|
||
|
res = sum = 0;
|
||
|
for (w = S.begin (); w != S.end (); w++)
|
||
|
{
|
||
|
if (w->second >= S.seuil)
|
||
|
{
|
||
|
pA = p_directe (w->first);
|
||
|
pB = B.p_directe (w->first);
|
||
|
res += (pA - pB >= 0) ? (pA - pB) * pA : (pB - pA) * pA; // |pA(w) - pB(w)|*pA(w)
|
||
|
sum += pA;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return sqrt (res / sum);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// renvoie la moyenne des Ècarts de log en fonction d'un Èchantillon S
|
||
|
double
|
||
|
PFA::dlog (const PFA & B, const Sample & S) const
|
||
|
{
|
||
|
Sample::const_iterator w;
|
||
|
double res, sum, pa;
|
||
|
res = sum = 0;
|
||
|
for (w = S.begin (); w != S.end (); w++)
|
||
|
{
|
||
|
sum += w->second;
|
||
|
pa = plog (w->first) - B.plog (w->first);
|
||
|
if (pa < 0)
|
||
|
pa = -pa;
|
||
|
res += pa * w->second;
|
||
|
}
|
||
|
return res / sum;
|
||
|
}
|
||
|
|
||
|
// renvoie la moyenne des Ècarts de log en fonction d'un Èchantillon S
|
||
|
double
|
||
|
PFA::dlog_safe (const PFA & B, const Sample & S) const
|
||
|
{
|
||
|
Sample::const_iterator w;
|
||
|
double res, pa;
|
||
|
int sum, nb_err, nb_mots;
|
||
|
|
||
|
res = sum = nb_err = nb_mots = 0;
|
||
|
for (w = S.begin (); w != S.end (); w++)
|
||
|
{
|
||
|
if (w->second >= S.seuil)
|
||
|
{
|
||
|
nb_mots++;
|
||
|
pa = plog (w->first) - B.plog (w->first);
|
||
|
if (!isnan (pa))
|
||
|
{
|
||
|
sum += w->second;
|
||
|
if (pa < 0)
|
||
|
pa = -pa;
|
||
|
res += pa * w->second;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (PFA_VERBOSE)
|
||
|
{
|
||
|
cerr << "\tErreur : ";
|
||
|
Word::const_iterator va;
|
||
|
for (va = w->first.begin ();
|
||
|
va != w->first.end (); va++)
|
||
|
cerr << alph.find (*va)->
|
||
|
second << " ";
|
||
|
cerr << endl;
|
||
|
cerr << "\tpA = " << plog (w->
|
||
|
first) <<
|
||
|
" et pB = " << B.plog (w->
|
||
|
first)
|
||
|
<< endl;
|
||
|
}
|
||
|
nb_err++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (PFA_VERBOSE)
|
||
|
{
|
||
|
if (nb_err > 0)
|
||
|
cerr << nb_err * 100 /
|
||
|
nb_mots << "% d'erreur de structure." << endl;
|
||
|
}
|
||
|
return res / sum;
|
||
|
}
|
||
|
|
||
|
// renvoie la divergence de Kullback Leibler relativemant ‡ l'Èchantillon S
|
||
|
double
|
||
|
PFA::divKL (const PFA & B, const Sample & S)
|
||
|
{
|
||
|
return B.perplexite (S) - perplexite (S);
|
||
|
}
|
||
|
|
||
|
// return true if it is a PRFA
|
||
|
bool
|
||
|
PFA::isPRFA (bool verbose)
|
||
|
{
|
||
|
if (!isPFA())
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// !!!!!!!!!!! VERSION NON DEFINITIVE !!!!!!!!!!!!!!
|
||
|
// !!!!! reduce is not yet implemented !!!!!!!!!
|
||
|
|
||
|
//reduce();
|
||
|
|
||
|
map < State, bool > resStates; // resStates[q]=true iff q is reach uniquely by some word.
|
||
|
set
|
||
|
< StateSet> Memory; // the set of states even founded.
|
||
|
StateSet QI; // l'ensemble des Ètats initiaux
|
||
|
StateSet R; // Un ensemble d'Ètats
|
||
|
StateSet Qm; // l'ensemble des Ètats dont on a dÈja trouvÈ un mot caractÈristique.
|
||
|
set
|
||
|
< StateSet >::const_iterator Ri;
|
||
|
set
|
||
|
< Word > W; // un ensemble de mots
|
||
|
Word w;
|
||
|
Word::iterator b;
|
||
|
StateSet::const_iterator q;
|
||
|
SFunc::iterator r;
|
||
|
Alphabet::const_iterator a;
|
||
|
|
||
|
//~ // -- //
|
||
|
//~ cout << "L'ensemble d'Ètats est : {";
|
||
|
//~ StateSet::const_iterator s;
|
||
|
//~ for (s=Q.begin() ; s != Q.end() ; ++s)
|
||
|
//~ cout << *s << ",";
|
||
|
//~ cout << "}" << endl;
|
||
|
//~ // -- //
|
||
|
|
||
|
// QI devient l'ensemble des Ètats initiaux
|
||
|
for (r=iota.begin();r != iota.end() ; ++r)
|
||
|
{
|
||
|
QI.insert(r->first);
|
||
|
}
|
||
|
|
||
|
//~ // -- //
|
||
|
//~ cout << "QI={";
|
||
|
//~ for (s=Q.begin() ; s != Q.end() ; ++s)
|
||
|
//~ cout << *s << ",";
|
||
|
//~ cout << "}" << endl;
|
||
|
//~ // -- //
|
||
|
|
||
|
|
||
|
// W = Sigma
|
||
|
for (a=Sigma.begin() ; a != Sigma.end() ; ++a)
|
||
|
{
|
||
|
w.clear();
|
||
|
w += *a;
|
||
|
//w.push_back(*a);
|
||
|
W.insert(w);
|
||
|
}
|
||
|
|
||
|
// Si il n'y a qu'un seul Ètat initial, alors
|
||
|
// son mot caractÈristique est epsilon
|
||
|
if (QI.size()==1)
|
||
|
{
|
||
|
Qm=QI;
|
||
|
if (verbose)
|
||
|
{
|
||
|
cout << "mot caractÈristique de " << *(Qm.begin()) << "\n";
|
||
|
cout << "epsilon\n";
|
||
|
cout << "longueur 0" << endl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// QI est la premiËre partie possible
|
||
|
Memory.insert(QI);
|
||
|
|
||
|
while(!W.empty() && !(Qm==Q))
|
||
|
{
|
||
|
w=*(W.begin()); // w=min W
|
||
|
W.erase(W.begin()); // W <- W \ {w}
|
||
|
R=delta(QI,w);
|
||
|
|
||
|
//~ // -- Affichage de delta (QI, w) -- //
|
||
|
//~ cout << "delta(QI," << affiche(w) << ")={";
|
||
|
//~ for (s = R.begin() ; s != R.end() ; ++s)
|
||
|
//~ cout << *s << ",";
|
||
|
//~ cout << "}" << endl;
|
||
|
//~ // -- //
|
||
|
|
||
|
// si R \notin Memory
|
||
|
if (Memory.find(R) == Memory.end())
|
||
|
{
|
||
|
// on rajoute R ‡ Memory
|
||
|
Memory.insert(R);
|
||
|
// W = W \cup w\Sigma
|
||
|
for (a=Sigma.begin() ; a != Sigma.end() ; ++a)
|
||
|
{
|
||
|
w += *a;
|
||
|
//w.push_back(*a);
|
||
|
W.insert(w);
|
||
|
b=w.end();
|
||
|
w.erase(--b);
|
||
|
}
|
||
|
|
||
|
// Si R contient un seul Ètat
|
||
|
if (R.size() == 1)
|
||
|
{
|
||
|
// Si cet Ètat n'a pas dÈja eu un mot caractÈristique
|
||
|
if (Qm.find(*(R.begin())) == Qm.end())
|
||
|
{
|
||
|
// Alors on a trouver un nouvel Ètat dont on connait le
|
||
|
// mot caractÈristique (w)
|
||
|
Qm.insert(*(R.begin()));
|
||
|
if (verbose)
|
||
|
{
|
||
|
cout << "le mot caracteristique de l'Ètat " << *(R.begin()) << " est :\n";
|
||
|
cout << affiche(w) << "\n";
|
||
|
cout << "longueur " << w.size() << endl;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return Qm==Q;
|
||
|
}
|
||
|
|
||
|
bool PFA::isPDFA()
|
||
|
{
|
||
|
if (!isPFA())
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
erase_transitions(0,0); // erasing null transition
|
||
|
if (iota.size() != 1)
|
||
|
return false;
|
||
|
Graph::const_iterator q;
|
||
|
LettreSFunc::const_iterator a;
|
||
|
SFunc::const_iterator r;
|
||
|
for (q=phi.begin() ; q != phi.end() ; ++q)
|
||
|
{
|
||
|
for (a=q->second.begin() ; a!=q->second.end() ; ++a)
|
||
|
{
|
||
|
if (a->second.size() > 1)
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|