diff --git a/src/sage/combinat/words/automataC.c b/src/sage/combinat/words/automataC.c new file mode 100644 index 00000000000..d0d8bfb4a4b --- /dev/null +++ b/src/sage/combinat/words/automataC.c @@ -0,0 +1,1494 @@ +#include +#include +#include +#include "Automaton.h" +#include "automataC.h" + +/* +static PyObject *DAError; + +static PyMethodDef dautomataMethods[] = +{ + {"system", system, METH_VARARGS, + "Execute a shell command."}, + {NULL, NULL, 0, NULL} // Sentinel +}; + +PyMODINIT_FUNC initdautomata(void) +{ + PyObject *m; + + m = Py_InitModule("dautomata", dautomataMethods); + if (m == NULL) + return; + + DAError = PyErr_NewException("dautomata.error", NULL, NULL); + Py_INCREF(DAError); + PyModule_AddObject(m, "error", DAError); +} +*/ + +typedef Automate Automaton; + +Dict NewDict (int n) +{ + Dict r; + r.n = n; + if (n == 0) + return r; + r.e = (int *)malloc(sizeof(int)*n); + if (!r.e) + { + printf("Out of memory !\n"); + exit(15); + } + int i; + for (i=0;in++; + d->e = (int *)realloc(d->e, sizeof(int)*d->n); + if (!d->e) + { + printf("Out of memory !"); + exit(1); + } + d->e[d->n-1] = e; +} + +Automaton NewAutomaton (int n, int na) +{ + Automaton a; + a.n = n; + a.na = na; + if (n == 0) + { + a.i = -1; + return a; + } + a.e = (Etat *)malloc(sizeof(Etat)*n); + if (!a.e) + { + printf("Out of memory !"); + exit(6); + } + int i; + for (i=0;i %d\n", i, j, a.e[i].f[j]); + } + } + } + printf("Etat initial %d.\n", a.i); +} + +void plotTikZ (Automaton 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].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); +} + +//détermine si les automates sont les mêmes (différents si états permutés) +bool equalsAutomaton (Automaton a1, Automaton a2) +{ + if (a1.n != a2.n || a1.na != a2.na) + return false; + int i, j; + for (i=0;ifinal = true; //indicate that the state has been visited + for (i=0;if[a]; + if (a != -1) + { + if (e2 < 0) + *next = -1; + else + { + //printf("(%d, %d)=%d -> (%d,%d)=%d\n", i, j, a, e1, e2, contract(e1, e2, a1.n)); + *next = contract(e1, e2, a1.n); + if (!r.e[*next].final) + Product_rec(r, e1, e2, a1, a2, d); + } + } + } + } +} + +Automaton Product(Automaton a1, Automaton a2, Dict d) +{ + //compte le nombre de lettres de l'alphabet final + int i, na=0; + for (i=0;i= na) + na = d.e[i]+1; + } + Automaton r = NewAutomaton(a1.n*a2.n, na); + init(r); + if (a1.i == -1 || a2.i == -1) + { + r.i = -1; + return r; + } + r.i = contract(a1.i, a2.i, a1.n); + Product_rec(r, a1.i, a2.i, a1, a2, d); + //met les états finaux + for (i=0;in++; + a->e = (Etat *)realloc(a->e, sizeof(Etat)*a->n); + if (!a->e) + { + printf("Out of memory !"); + exit(2); + } + a->e[a->n-1].f = (int *)malloc(sizeof(int)*a->na); + if (!a->e[a->n-1].f) + { + printf("Out of memory !"); + exit(3); + } + int i; + for (i=0;ina;i++) + { + a->e[a->n-1].f[i] = -1; + } + a->e[a->n-1].final = final; +} + +Etats NewEtats (int n) +{ + Etats e; + e.n = n; + e.e = (int *)malloc(sizeof(int)*n); + if (!e.e) + { + printf("Out of memory !"); + exit(7); + } +return e; +} + +void FreeEtats (Etats e) +{ + free(e.e); +} + +void initEtats (Etats e) +{ + int i; + for (i=0;in;i++) + { + if (equals(l->e[i], e)) + { + if (res) + *res = i; + return false; + } + } + //ajoute l'élément + l->n++; + l->e = (Etats*)realloc(l->e, sizeof(Etats)*l->n); + if (!l->e) + { + printf("Out of memory !"); + exit(4); + } + l->e[l->n-1] = copy(e); + if (res) + *res = l->n-1; + return true; +} + +//ajoute un élément même s'il est déjà dans la liste +void AddEl2 (ListEtats *l, Etats e) +{ + //ajoute l'élément + l->n++; + l->e = (Etats*)realloc(l->e, sizeof(Etats)*l->n); + if (!l->e) + { + printf("Out of memory !"); + exit(5); + } + l->e[l->n-1] = copy(e); +} + +Dict* lhash; +int nhash = 10000019; + +void AllocHash () +{ + lhash = (Dict*)malloc(sizeof(Dict)*nhash); + if (!lhash) + { + printf("Out of memory !"); + exit(8); + } + int i; + 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 (nf) + *nf = v; + if (v < 0) + return false; + if (equals(l->e[v], e)) + { + //printf("equals !\n"); + return false; + } + } + //ajoute l'élément + if (nf) + *nf = l->n; + //printf("Add dict...\n"); + dictAdd(&lhash[h], l->n); + return true; +} + +InvertDict NewInvertDict (int n) +{ + InvertDict r; + r.n = n; + if (n == 0) + return r; + r.d = (Dict*)malloc(sizeof(Dict)*n); + if (!r.d) + { + printf("Out of memory !"); + exit(9); + } + return r; +} + +InvertDict invertDict (Dict d) +{ + //compte le nombre de valeurs différentes (supposées consécutives) + int i; + int nv = 0; + for (i=0;i= nv) + nv = d.e[i]+1; + } + //printf("nombre d'éléments : %d\n", nv); + //alloue l'inverse + InvertDict r; + r.n = nv; + r.d = (Dict *)malloc(sizeof(Dict)*nv); + if (!r.d) + { + printf("Out of memory !"); + exit(10); + } + //initialise + for (i=0;in;i++) + { + if (f->e[i] == ef) + return; + } + f->e[f->n] = ef; + f->n++; +} + +//Etats : liste d'états de a +void Determinise_rec (Automaton a, InvertDict id, Automaton* r, ListEtats* l, bool onlyfinals, bool nof, int niter) +{ + int current = l->n-1; + Etats c = l->e[current]; + //Parcours les fils + Etats f = NewEtats(a.n); + int nf; + Etat e; + int i,j,k; + int ef; + bool final; + + //printf("%d\n", niter); + //printf("l = "); + //printListEtats(*l); + //printf("c = "); + //printEtats(c); + + for (i=0;ie[current].f[i] = nf; + //printf("Add %d --%d--> %d\n", current, i, nf); + //printAutomaton(*r); + } + } + FreeEtats(f); +} + +Automaton Determinise (Automaton a, Dict d, bool noempty, bool onlyfinals, bool nof, bool verb) +{ + 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); + } + } + } + // + + if (verb) + { + if (onlyfinals) + printf("onlyfinals\n"); + if (nof) + printf("nof\n"); + if (noempty) + printf("noempty\n"); + printf("Dictionnaire : "); + printDict(d); + } + + //calcule l'inverse du dictionnaire + InvertDict id = invertDict(d); + if (verb && id.n == d.n) + { + printf("Le dictionnaire est inversible : déterminisation triviale !\n"); + } + + if (verb) + { + printf("Dictionnaire inverse :\n"); + printInvertDict(id); + } + + //alloue la table de hachage + AllocHash(); + //met l'ensemble vide dans la table de hachage si cet état n'est pas souhaité dans r + if (noempty) + { + Etats e = NewEtats(0); //ensemble vide + int h = hash(e); + if (verb) + printf("hash vide : %d\n", h); + dictAdd(&lhash[h], -1); + } + + //initialise l'automate résultat avec juste l'état initial + if (verb) + printf("Init r...\n"); + Automaton r; + if (a.i == -1) + { + if (verb) + printf("Pas d'état initial !\n"); + if (nof) + { + r = NewAutomaton(1, id.n); + r.i = 0; + r.e[0].final = true; + for (i=0;i %d\n", i, j, f); + r.e[f].f[j] = i; + } + } + } + return r; +} + +int min (int a, int b) +{ + if (a < b) + return a; + return b; +} + +int compteur2; +void StronglyConnectedComponents_rec(Automaton a, int etat, int *pile, int *m, int *res) +{ + //printf("etat=%d, cpt=%d, cpt2=%d\n", etat, compteur, compteur2); + int j,f,c; + pile[compteur] = etat; + m[etat] = compteur; + c = compteur; + a.e[etat].final |= 2; //note que l'état a été vu + compteur++; + for (j=0;j %d\n", f); + if (!(a.e[f].final & 2)) + { + StronglyConnectedComponents_rec(a, f, pile, m, res); + m[etat] = min(m[etat], m[f]); + }else if (res[f] == -1) + { + m[etat] = min(m[etat], m[f]); + } + } + //printf("m[%d]=%d, c=%d\n", etat, m[etat], c); + if (m[etat] == c) + { //on a une composante fortement connexe + //dépile la composante + do + { + compteur--; + res[pile[compteur]] = compteur2; + }while(pile[compteur] != etat); + compteur2++; + } +} + +//Tarjan algorithm +int StronglyConnectedComponents (Automaton a, int *res) +{ + int *m = (int *)malloc(sizeof(int)*a.n); + int *pile = (int *)malloc(sizeof(int)*a.n); + int i; + for (i=0;i= c) + c = l[i]+1; + } + //créé le nouvel automate + Automaton r = NewAutomaton(c, a.na); + + /////////////////////////////////////////////Not implemented !!! + + return r; +} +*/ + +//détermine les sommets accessible et co-accessibles +bool emonde_rec (Automaton a, int *l, InvertDict id, int etat) +{ + //printf("emonde_rec %d...\n", etat); + int i, j, f; + a.e[etat].final |= 2; //note que le sommet est en cours d'étude + for (i=0;i