diff --git a/src/sage/combinat/words/Automaton.h b/src/sage/combinat/words/Automaton.h index f7cd560b2c1..2cace21711f 100644 --- a/src/sage/combinat/words/Automaton.h +++ b/src/sage/combinat/words/Automaton.h @@ -20,3 +20,31 @@ struct Automate // int nalloc; //usage interne, mémoire allouée }; typedef struct Automate Automate; + +/////////////////////////////////////////////////////// +//Automates non déterministe +/////////////////////////////////////////////////////// + +struct Arete +{ + int l; //label + int e; //état d'arrivée +}; +typedef struct Arete Arete; + +struct NEtat +{ + Arete *a; + int n; + bool final; + bool initial; +}; +typedef struct NEtat NEtat; + +struct NAutomate +{ + NEtat *e; //états + int n; //nombre d'états + int na; //nombre de lettres +}; +typedef struct NAutomate NAutomate; diff --git a/src/sage/combinat/words/automataC.c b/src/sage/combinat/words/automataC.c index 103cae68033..bad91bc4c89 100644 --- a/src/sage/combinat/words/automataC.c +++ b/src/sage/combinat/words/automataC.c @@ -9,22 +9,22 @@ static PyObject *DAError; static PyMethodDef dautomataMethods[] = { - {"system", system, METH_VARARGS, - "Execute a shell command."}, - {NULL, NULL, 0, NULL} // Sentinel + {"system", system, METH_VARARGS, + "Execute a shell command."}, + {NULL, NULL, 0, NULL} // Sentinel }; PyMODINIT_FUNC initdautomata(void) { - PyObject *m; + PyObject *m; - m = Py_InitModule("dautomata", dautomataMethods); - if (m == NULL) - return; + m = Py_InitModule("dautomata", dautomataMethods); + if (m == NULL) + return; - DAError = PyErr_NewException("dautomata.error", NULL, NULL); - Py_INCREF(DAError); - PyModule_AddObject(m, "error", DAError); + DAError = PyErr_NewException("dautomata.error", NULL, NULL); + Py_INCREF(DAError); + PyModule_AddObject(m, "error", DAError); } */ @@ -135,6 +135,93 @@ void FreeAutomaton (Automaton *a) a->n = 0; } +NAutomaton NewNAutomaton (int n, int na) +{ + NAutomaton a; + a.n = n; + a.na = na; + if (n == 0) + { + return a; + } + a.e = (NEtat *)malloc(sizeof(NEtat)*n); + if (!a.e) + { + printf("Out of memory !"); + exit(6); + } + int i; + for (i=0;ie = (NEtat*)realloc(a->e, sizeof(NEtat)*n); + if (a->n < n) + { + int i; + for (i=a->n;ie[i].a = NULL; + a->e[i].n = 0; + } + } + a->n = n; +} + +void FreeNAutomaton (NAutomaton *a) +{ + if (a->n == 0) + return; + int i; + for (i=0;in;i++) + { + if (a->e[i].n > 0) + { + free(a->e[i].a); + } + } + free(a->e); + a->n = 0; +} + +void ReallocAutomaton (Automaton *a, int n, bool init) +{ + if (a->n > n) + { + //libère les états à supprimmer + int i; + for (i=n;in;i++) + { + free(a->e[i].f); + } + } + a->e = (Etat*)realloc(a->e, sizeof(Etat)*n); + if (a->n < n) + { + int i; + for (i=a->n;ie[i].f = (int *)malloc(sizeof(int)*a->na); + if (init) + { + int j; + for (j=0;jna;j++) + { + a->e[i].f[j] = -1; + } + } + } + } + a->n = n; +} + +/* void ReallocAutomaton (Automaton *a, int n) { //////////////////fonction BUGUéE !!!!!!!!!!!!!!!!!!! int i; @@ -205,8 +292,9 @@ void ReallocAutomaton (Automaton *a, int n) } } a->n = n; - */ + *//* } +*/ Automaton CopyAutomaton (Automaton a, int nalloc, int naalloc) { @@ -283,33 +371,95 @@ void plotTikZ (Automaton a, const char **labels, const char *graph_name, double // "orientation = Landscape\n"); if (verb) printf("write...\n"); - - fprintf(f, " \n"); - int i,j; - for (i=0;i %d [label=\"%s\"]\n", i, a.e[i].f[j], labels[j]); - } - } - fprintf(f, "}\n"); + + fprintf(f, " \n"); + int i,j; + for (i=0;i %d [label=\"%s\"]\n", i, a.e[i].f[j], labels[j]); + } + } + fprintf(f, "}\n"); + + fclose(f); + if (verb) + printf("draw...\n"); + sprintf(tamp, "dot %s -Gname -Tsvg > output%d%d.svg", name, time(NULL), clock()); + system(tamp); +} + +void NplotTikZ (NAutomaton a, const char **labels, const char *graph_name, double sx, double sy) +{ + bool verb = false; + const char *name = "/Users/mercat/Desktop/a.dot"; + char tamp[1024]; + FILE *f = fopen(name, "w"); + if (!f) + { + printf("Impossible d'ouvrir le fichier a.dot !\n"); + return; + } + + if (verb) + printf("start...\n"); + fprintf(f, "digraph %s\n{\n"\ + " node[fontsize=20]"\ + " edge[fontsize=20, arrowhead = open]"\ + " rankdir = LR;\n"\ + " size = \"%lf, %lf\";\n"\ + " center = 1;\n"\ + " nodesep = \"0.2\"\n", graph_name, sx, sy); +// " ranksep = \"0.4 equally\";\n", graph_name); +// " rotate = -90\n"\ +// " orientation=landscape\n"\ +// "orientation = Landscape\n"); + if (verb) + printf("write...\n"); + + fprintf(f, " \n"); + int i,j; + for (i=0;i %d [label=\"%s\"]\n", i, a.e[i].a[j].e, labels[a.e[i].a[j].l]); + } + } + fprintf(f, "}\n"); fclose(f); if (verb) @@ -724,6 +874,199 @@ void AddEl2 (ListEtats *l, Etats e) l->e[l->n-1] = copy(e); } +/////////////////////////////////////////////////////////////////// +Etats2 NewEtats2 (int n) +{ + Etats2 e; + e.n = n; + e.e = (uint64 *)malloc(sizeof(uint64)*((n+63)/64)); + if (!e.e) + { + printf("Out of memory !"); + exit(7); + } +return e; +} + +void FreeEtats2 (Etats2 e) +{ + free(e.e); +} + +void initEtats2 (Etats2 e) +{ + int i; + int n = (e.n+63)/64; + for (i=0;ie[i/64] |= ((uint64)1<<(i%64)); +} + +ListEtats2 NewListEtats2(int n, int na) +{ + ListEtats2 r; + r.n = n; + r.na = na; + r.e = (Etats2*)malloc(sizeof(Etats2)*na); + return r; +} + +void ReallocListEtats2(ListEtats2 *l, int n, bool marge) +{ + l->n = n; + if (!marge) + { + l->na = n; + l->e = (Etats2*)realloc(l->e, sizeof(Etats2)*n); + }else + { + if (n > l->na) + { + l->na = l->n*2; + l->e = (Etats2*)realloc(l->e, sizeof(Etats2)*l->na); + } + } +} + +void FreeListEtats2 (ListEtats2* l) +{ + int i; + for (i=0;in;i++) + { + FreeEtats2(l->e[i]); + } + free(l->e); + l->n = 0; + l->na = 0; +} + +void printListEtats2 (ListEtats2 l) +{ + int i; + for (i=0;in++; + l->e = (Etats2*)realloc(l->e, sizeof(Etats2)*l->n); + if (!l->e) + { + printf("Out of memory !"); + exit(5); + } + l->e[l->n-1] = copyEtats2(e); +} + +//ajoute un élément s'il n'est pas déjà dans la liste +bool AddEtats2 (ListEtats2 *l, Etats2 e, int* res) +{ + int i; + for (i=0;in;i++) + { + if (equals2(l->e[i], e)) + { + if (res) + *res = i; + return false; + } + } + //ajoute l'élément + addEtats2(l, e); + return true; +} +*/ + +/////////////////////////////////////////////////////////////////// + Dict* lhash; int nhash = 10000019; @@ -761,6 +1104,50 @@ int hash (Etats e) return h; } +int hash2 (Etats2 e) +{ + int i; + uint64 h = 1; + int n = (e.n+63)/64; + for (i=0;i= l->n) + { + printf("***************\nErreur : élément de la table de hachage trop grand !!!\n****************\n"); + } + ///////////// + v = lhash[h].e[i]; + if (k) + *k = v; + if (equalsEtats2(l->e[v], e)) + { + //printf("equals !\n"); + return false; + } + } + //ajoute l'élément + if (k) + *k = l->n; + //printf("Add dict...\n"); + dictAdd(&lhash[h], l->n); + return true; +} + //ajoute l'élément s'il n'est pas déjà dans la table de hashage bool add (const ListEtats *l, Etats e, int* nf) { @@ -963,26 +1350,26 @@ Automaton Determinise (Automaton a, Dict d, bool noempty, bool onlyfinals, bool int i; //increase the stack size - const rlim_t kStackSize = 32 * 1024 * 1024; // min stack size = 1024 MB - struct rlimit rl; - int result; - result = getrlimit(RLIMIT_STACK, &rl); - if (result == 0) - { - if (rl.rlim_cur < kStackSize) - { - if (verb) - printf("limite : %d -> %d\n", rl.rlim_cur, kStackSize); - rl.rlim_cur = kStackSize; - result = setrlimit(RLIMIT_STACK, &rl); - if (result != 0) - { - fprintf(stderr, "setrlimit returned result = %d\n", result); - } - } - } - // - + const rlim_t kStackSize = 32 * 1024 * 1024; + struct rlimit rl; + int result; + result = getrlimit(RLIMIT_STACK, &rl); + if (result == 0) + { + if (rl.rlim_cur < kStackSize) + { + if (verb) + printf("limite : %d -> %d\n", rl.rlim_cur, kStackSize); + rl.rlim_cur = kStackSize; + result = setrlimit(RLIMIT_STACK, &rl); + if (result != 0) + { + fprintf(stderr, "setrlimit returned result = %d\n", result); + } + } + } + // + if (verb) { if (onlyfinals) @@ -1107,6 +1494,125 @@ Automaton Determinise (Automaton a, Dict d, bool noempty, bool onlyfinals, bool return r; } +Automaton DeterminiseN (NAutomaton a, bool puits) +{ + int verb = 0; + if (verb) + printf("allocation...\n"); + + Automaton r = NewAutomaton(a.n, a.na); + //printf("Not implemented yet !!!\n"); + + if (a.n == 0) + return r; + + if (verb >= 20) + printf("alloue la table de hashage...\n"); + + AllocHash(); + + if (verb >= 20) + printf("alloue les états...\n"); + + int i,j,k,u; + ListEtats2 l = NewListEtats2(1, 1024); + Etats2* e = (Etats2*)malloc(sizeof(Etats2)*a.na); + for (i=0;i= 20) + printf("alloue le premier état...\n"); + + //initialise le premier état + r.i = 0; + l.e[0] = NewEtats2(a.n); + initEtats2(l.e[0]); + for (i=0;i= 20) + { + printf("état %d : ", i); + printEtats2(l.e[i]); + } + + r.e[i].final = false; + for (j=0;j 20) + printf(" -> états atteints :\n"); + for (j=0;j 20) + { + printf(" "); + printEtats2(e[j]); + } + if (puits || !isNullEtats2(e[j])) + { + //détermine si l'état est nouveau ou pas + if (addEtats2(&l, e[j], &k)) + { + ReallocListEtats2(&l, l.n+1, true); + l.e[k] = copyEtats2(e[j]); + //ajoute un état à l'automate + if (l.n > r.n) + { //alloue de la mémoire si nécessaire + ReallocAutomaton(&r, 2*l.n, false); + } + } + //ajoute une arête vers k étiquetée par j dans le nouvel automate + r.e[i].f[j] = k; + }else + { + r.e[i].f[j] = -1; + } + } + } + + if (verb) + printf("free...\n"); + + //libère la mémoire + ReallocNAutomaton(&r, l.n); + FreeListEtats2(&l); + for (i=0;i + +typedef uint64_t uint64; +typedef unsigned int uint; typedef Automate Automaton; +typedef NAutomate NAutomaton; struct Dict { @@ -13,7 +18,9 @@ void FreeDict (Dict d); void printDict (Dict d); void dictAdd (Dict *d, int e); //ajoute un élément au dictionnaire (même s'il était déjà présent) Automaton NewAutomaton (int n, int na); +void ReallocNAutomaton (NAutomaton *a, int n); void FreeAutomaton (Automaton *a); +void FreeNAutomaton (NAutomaton *a); Automaton CopyAutomaton (Automaton a, int nalloc, int naalloc); void init (Automaton *a); void printAutomaton (Automaton a); @@ -50,6 +57,40 @@ void printListEtats (ListEtats l); bool AddEl (ListEtats *l, Etats e, int* res); //ajoute un élément s'il n'est pas déjà dans la liste void AddEl2 (ListEtats *l, Etats e); //ajoute un élément même s'il est déjà dans la liste +//////////////// +struct Etats2 +{ + uint n; + uint64 *e; +}; +typedef struct Etats2 Etats2; + +Etats2 NewEtats2 (int n); +void FreeEtats2 (Etats2 e); +void initEtats2 (Etats2 e); +void printEtats2 (Etats2 e); +bool isNullEtats2 (Etats2 e); +bool equalsEtats2 (Etats2 e1, Etats2 e2); +inline bool hasEtats2 (Etats2 e, uint64 i); +Etats2 copyEtats2 (Etats2 e); +void addEtat (Etats2 *e, uint64 i); + +struct ListEtats2 +{ + Etats2 *e; + int n; //nombre d'états + int na; //mémoire allouée +}; +typedef struct ListEtats2 ListEtats2; + +ListEtats2 NewListEtats2(int n, int na); +void ReallocListEtats2(ListEtats2* l, int n, bool marge); +void FreeListEtats2 (ListEtats2* l); +void printListEtats2 (ListEtats2 l); +//bool AddEtats2 (ListEtats2 *l, Etats2 e, int* res); //ajoute un élément s'il n'est pas déjà dans la liste +//void addEtats2 (ListEtats2 *l, Etats2 e); //ajoute un élément même s'il est déjà dans la liste +//////////////// + //inverse d'un dictionnaire struct InvertDict { @@ -66,6 +107,8 @@ void putEtat (Etats *f, int ef); ////////////////////////////////// à améliore void Determinise_rec (Automaton a, InvertDict id, Automaton* r, ListEtats* l, bool onlyfinals, bool nof, int niter); Automaton Determinise (Automaton a, Dict d, bool noempty, bool onlyfinals, bool nof, bool verb); +Automaton DeterminiseN (NAutomaton a, bool puits); + //change l'alphabet en dupliquant des arêtes si nécessaire //the result is assumed deterministic !!!! Automaton Duplicate (Automaton a, InvertDict id, int na2, bool verb); @@ -74,7 +117,10 @@ Automaton Duplicate (Automaton a, InvertDict id, int na2, bool verb); Automaton emonde_inf (Automaton a, bool verb); //Compute the transposition, assuming it is deterministic -Automaton Transpose (Automaton a); +Automaton TransposeDet (Automaton a); + +//Compute the transposition +NAutomaton Transpose (Automaton a); //Tarjan algorithm int StronglyConnectedComponents (Automaton a, int *res); diff --git a/src/sage/combinat/words/cautomata.pxd b/src/sage/combinat/words/cautomata.pxd index 4d1d1db7e95..24bd405ae85 100644 --- a/src/sage/combinat/words/cautomata.pxd +++ b/src/sage/combinat/words/cautomata.pxd @@ -16,3 +16,22 @@ cdef extern from "Automaton.h": cdef class FastAutomaton: cdef Automate* a cdef list A + +cdef extern from "Automaton.h": + ctypedef char bool + cdef cppclass Arete: + int l #label + int e #état d'arrivée + cdef cppclass NEtat: + Arete* a + int n + bool final + bool initial + cdef cppclass NAutomate: + NEtat* e #états + int n #nombre d'états + int na #nombre de lettres + +cdef class NFastAutomaton: + cdef NAutomate* a + cdef list A diff --git a/src/sage/combinat/words/cautomata.pyx b/src/sage/combinat/words/cautomata.pyx index 8866bf3bc81..effa924d25f 100644 --- a/src/sage/combinat/words/cautomata.pyx +++ b/src/sage/combinat/words/cautomata.pyx @@ -31,6 +31,7 @@ include "sage/ext/interrupt.pxi" cdef extern from "automataC.h": ctypedef Automate Automaton + ctypedef NAutomate NAutomaton cdef cppclass Dict: int* e int n @@ -40,12 +41,15 @@ cdef extern from "automataC.h": Automaton NewAutomaton (int n, int na) void FreeAutomaton (Automaton *a) + void FreeNAutomaton (NAutomaton *a) Automaton CopyAutomaton (Automaton a, int nalloc, int naalloc) void init (Automaton *a) void printAutomaton (Automaton a) void plotTikZ (Automaton a, const char **labels, const char *graph_name, double sx, double sy) + void NplotTikZ (NAutomaton a, const char **labels, const char *graph_name, double sx, double sy) Automaton Product(Automaton a1, Automaton a2, Dict d) Automaton Determinise (Automaton a, Dict d, bool noempty, bool onlyfinals, bool nof, bool verb) + Automaton DeterminiseN (NAutomaton a, bool puits) Automaton emonde_inf (Automaton a, bool verb) Automaton emonde (Automaton a, bool verb) Automaton emondeI (Automaton a, bool verb) @@ -57,7 +61,8 @@ cdef extern from "automataC.h": void FreeInvertDict (InvertDict id) void printInvertDict (InvertDict id) Automaton Duplicate (Automaton a, InvertDict id, int na2, bool verb) - Automaton Transpose (Automaton a) + Automaton TransposeDet (Automaton a) + NAutomaton Transpose (Automaton a) int StronglyConnectedComponents (Automaton a, int *res) Automaton SubAutomaton (Automaton a, Dict d, bool verb) Automaton Permut (Automaton a, int *l, int na, bool verb) @@ -318,6 +323,58 @@ cdef Bool (int x): return True return False +cdef class NFastAutomaton: + +# cdef NAutomaton* a +# cdef list A + + def __cinit__ (self): + #print "cinit" + self.a = malloc(sizeof(NAutomaton)) + #initialise + self.a[0].e = NULL + self.a[0].n = 0 + self.a[0].na = 0 + self.A = [] + + def __init__(self, a, i=None, F=None, A=None): + #print "init" + if a is None: + return + else: + raise ValueError("Cannot construct directly a NFastAutomaton for the moment.") + + def __dealloc__ (self): + #print "free" + FreeNAutomaton(self.a) + free(self.a) + + def __repr__ (self): + return "NFastAutomaton with %d states and an alphabet of %d letters"%(self.a.n, self.a.na) + + def determinise (self, puits=False): + cdef Automaton a + sig_on() + r = FastAutomaton(None) + a = DeterminiseN(self.a[0], puits) + r.a[0] = a + r.A = self.A + sig_off() + return r + + def plot (self, int sx=10, int sy=8): + sig_on() + cdef char** ll + ll = malloc(sizeof(char*)*self.a.na) + cdef int i + strA = [] + for i in range(self.a.na): + strA.append(str(self.A[i])) + ll[i] = strA[i] + NplotTikZ(self.a[0], ll, "Automaton", sx, sy) + free(ll); + sig_off() + cdef class FastAutomaton: # cdef Automaton* a @@ -764,9 +821,17 @@ cdef class FastAutomaton: self.A = A sig_off() - def transpose (self): + def transpose_det (self): sig_on() r = FastAutomaton(None) + r.a[0] = TransposeDet(self.a[0]) + r.A = self.A + sig_off() + return r + + def transpose (self): + sig_on() + r = NFastAutomaton(None) r.a[0] = Transpose(self.a[0]) r.A = self.A sig_off() diff --git a/src/sage/monoids/beta_adic_monoid.pyx b/src/sage/monoids/beta_adic_monoid.pyx index 74df3d71666..dd2fa947d73 100644 --- a/src/sage/monoids/beta_adic_monoid.pyx +++ b/src/sage/monoids/beta_adic_monoid.pyx @@ -1817,7 +1817,7 @@ class BetaAdicMonoid(Monoid_class): return ssd - def reduced_words_automaton2 (self, step=100, verb=False): + def reduced_words_automaton2 (self, step=100, verb=False, transpose=False): r""" Compute the reduced words automaton of the beta-adic monoid (without considering the automaton of authorized words). See http://www.latp.univ-mrs.fr/~paul.mercat/Publis/Semi-groupes%20fortement%20automatiques.pdf for a definition of such automaton. @@ -1839,6 +1839,8 @@ class BetaAdicMonoid(Monoid_class): Cdp = [k for k in range(len(Cd)) if Cd[k] in [self.C[j]-self.C[i] for i in range(len(self.C)) for j in range(i)]] #indices des chiffres strictements négatifs dans Cd arel = self.relations_automaton3(Cd=Cd, ext=False) arel = arel.emonde() + if transpose: + arel = arel.transpose() if verb: print "arel = %s"%arel if step == 1: