staticint fsa_checkmult_short(fsa *multptr, reduction_equation *eqnptr, int maxeqns, boolean cosets, int separator); staticint fsa_checkmult_int(fsa *multptr, reduction_equation *eqnptr, int maxeqns, boolean cosets, int separator);
/* If the checking fails, the failing words will be returned in the lhs of *eqnptr[i],andtheassociatedgeneratorintherhs,fori=0,1,... *Ifmorethanmaxeqnssuchwordsarefound,weabort. *Thefunctionreturnsthenumberofequationsfound.
*/ int fsa_checkmult(fsa *multptr, reduction_equation *eqnptr, int maxeqns,
boolean cosets, int separator)
{ if (kbm_print_level >= 3)
printf(" #Calling fsa_checkmult.\n"); if (multptr->states->size < MAXUSHORT) return fsa_checkmult_short(multptr, eqnptr, maxeqns, cosets, separator); else return fsa_checkmult_int(multptr, eqnptr, maxeqns, cosets, separator);
}
/* If the checking fails, the failing word will be returned in the lhs of **eqnptr,andtheassociatedgeneratorintherhs.
*/ staticint fsa_checkmult_short(fsa *multptr, reduction_equation *eqnptr, int maxeqns, boolean cosets, int separator)
{ int **table, dr, ne, ngens, ngens1, ns, nsnew, bstate, numeqns, e, es, ef,
espad, efpad, cstate, cs, csi, i, j, g1, bg1, im, len; unsignedshort *ht_ptr, *ht_chptr, *ht_ptrb, *ht_ptre, *cs_ptr, *cs_ptre,
*ptr;
gen **genlist, *genptr;
boolean dense_ip, *occurs, *includes, got;
setToLabelsType *state_label;
short_hash_table ht; int maxv = 65536; struct vertexd {
gen g; int state;
} * definition, *newdef; /* This is used to store the defining transition for the states of the new *fsa.Ifdefinition[i]=v,thenstateiisdefinedbythetransitionfrom *statev.state,withgeneratorv.g. *State1doesnothaveadefinition.
*/
if (kbm_print_level >= 3)
printf(" #Calling fsa_checkmult_short.\n"); if (!multptr->flags[DFA]) {
fprintf(stderr, "Error: fsa_checkmult only applies to DFA's.\n"); return -1;
}
if (multptr->alphabet->type != PRODUCT || multptr->alphabet->arity != 2) {
fprintf(stderr, "Error in fsa_checkmult: fsa must be 2-variable.\n"); return -1;
} if (multptr->states->type != LABELED) {
fprintf(stderr, "Error in fsa_checkmult: states of fsa must be of labeled type.\n"); return -1;
}
/* We are not actually going to construct a new fsa - we just go through the *motionsofconstructingthehash-tablethatrepresentsitsstates.
*/
ne = multptr->alphabet->size;
ngens = multptr->alphabet->base->size;
ngens1 = ngens + 1;
state_label = multptr->states->setToLabels;
ns = multptr->states->size;
if (ne != ngens1 * ngens1 - 1) {
fprintf(stderr, "Error: in a 2-variable fsa, alphabet size should = " "(ngens+1)^2 - 1.\n"); return -1;
}
tmalloc(occurs, boolean, ngens + 1); for (i = 0; i <= ngens; i++)
occurs[i] = FALSE; for (i = 1; i <= ns; i++) if ((j = state_label[i])) {
genlist = multptr->states->labels->wordslist[j]; /* the list of words that is the label for state number *ptr */ while ((genptr = *(genlist++)))
occurs[genptr[0]] = TRUE;
}
short_hash_init(&ht, FALSE, 0, 0, 0);
ht_ptr = ht.current_ptr;
ht_ptr[0] = multptr->initial[1];
im = short_hash_locate(&ht, 1); /* Each state in the new fsa will be represented as a subset of the set of *states*of*multptr.Theinitialstateisone-elementsetcontaining *theinitialstateof*multptr. *Thesubsetswillbestoredasvariable-lengthrecordsinthehash-table, *alwaysinincreasingorder.
*/ if (im != 1) {
fprintf(stderr, "Hash-initialisation problem in fsa_checkmult.\n"); return -1;
}
/* Set up the array of structures to remember state-definitions. */
tmalloc(definition, struct vertexd, maxv);
nsnew = 1;
tmalloc(includes, boolean, ngens + 2); /* this will be used for checking validity of new states - *includes[ngens+1]isnotused,butmaybereferencedaccidentally
*/
cstate = 0;
numeqns = 0;
while (++cstate <= ht.num_recs) { if (kbm_print_level >= 3) { if ((cstate <= 1000 && cstate % 100 == 0) ||
(cstate <= 10000 && cstate % 1000 == 0) ||
(cstate <= 100000 && cstate % 5000 == 0) || cstate % 50000 == 0)
printf(" #cstate = %d; number of states = %d.\n", cstate,
ht.num_recs);
}
cs_ptr = short_hash_rec(&ht, cstate);
cs_ptre = short_hash_rec(&ht, cstate) + short_hash_rec_len(&ht, cstate) - 1; for (g1 = 1; g1 <= ngens; g1++) { /* Calculate action of generator g1 on state cstate - to get the image, *wehavetoapply(g1,g2)toeachelementinthesubsetcorrespondingto *cstate,andthisforeachgeneratorg2ofthebase-alphabet(including *thepaddingsymbol).
*/
ht_ptrb = ht.current_ptr;
ht_ptre = ht_ptrb - 1;
ptr = cs_ptr - 1;
es = (g1 - 1) * ngens1 + 1;
ef = g1 * ngens1; /* As g2 ranges from 1 to ngens+1 in the pair (g1,g2), for fixed g1, the *correspondingedgenumberinthefsarangesfromestoef.
*/
while (++ptr <= cs_ptre) {
cs = *ptr; for (e = es; e <= ef; e++) {
csi = target(dense_ip, table, e, cs, dr); if (csi == 0) continue; if (ht_ptrb > ht_ptre || csi > *ht_ptre) { /* We have a new state for the image subset to be added to the end
*/
*(++ht_ptre) = csi;
} else {
ht_chptr = ht_ptrb; while (*ht_chptr < csi)
ht_chptr++; if (csi < *ht_chptr) { /* we have a new state for the image subset to be added in the
* middle */
ht_ptr = ++ht_ptre; while (ht_ptr > ht_chptr) {
*ht_ptr = *(ht_ptr - 1);
ht_ptr--;
}
*ht_ptr = csi;
}
}
}
}
im = short_hash_locate(&ht, ht_ptre - ht_ptrb + 1); if (im == -1) return -1; if (im > nsnew) { /* We have a new state. We must check to see if it is valid - i.e. *containsanaccept-stateofeachmultiplier.Butfirstwehaveto *closeitundertheactionof($,g)forgeneratorsg.(Wecanput *extrastatesfoundattheend-thiswillnotdisturbthe *hash-table.)
*/
espad = ngens * ngens1 + 1;
efpad = ngens1 * ngens1 - 1;
ptr = ht_ptrb - 1; while (++ptr <= ht_ptre) {
cs = *ptr; for (e = espad; e <= efpad; e++) {
csi = target(dense_ip, table, e, cs, dr); if (csi == 0) continue; /* see if csi is new */
ht_chptr = ht_ptrb - 1;
got = FALSE; while (++ht_chptr < ht_ptre) if (csi == *ht_chptr) {
got = TRUE; break;
} if (!got) /* add csi to the end */
*(++ht_ptre) = csi;
}
} /* State is now closed under ($,g) - so check validity */ for (i = 0; i <= ngens; i++)
includes[i] = FALSE;
ptr = ht_ptrb - 1; while (++ptr <= ht_ptre) if ((j = state_label[*ptr])) {
genlist = multptr->states->labels->wordslist[j]; /* the list of words that is the label for state number *ptr */ while ((genptr = *(genlist++)))
includes[genptr[0]] = TRUE;
}
for (i = 0; i <= ngens; i++) if (occurs[i] && !includes[i]) { /* The state is invalid for generator number i. *Wereconstructtheoffendingwordw,usingthestate-definitions, *andthenabort.
*/ if (numeqns == 0 && kbm_print_level > 0)
printf("#Multiplier incorrect with generator number %d.\n", i); /* First see how long the word is */
len = 1;
bg1 = g1;
bstate = cstate; while (bstate != 1) {
len++;
bg1 = definition[bstate].g;
bstate = definition[bstate].state;
} /* Now allocate space for it - allow an extra place for multiplying *byagenerator. *Inthecosetscase,alsoanextraplacefortheseparator *thatweinsertatthebeginningoftheword.
*/ if (cosets)
len++;
tmalloc(eqnptr[numeqns].lhs, gen, len + 2);
eqnptr[numeqns].lhs[len] = 0;
bg1 = g1;
bstate = cstate; while (1) {
eqnptr[numeqns].lhs[--len] = bg1; if (bstate == 1) break;
bg1 = definition[bstate].g;
bstate = definition[bstate].state;
} if (cosets)
eqnptr[numeqns].lhs[--len] = separator; /* Put the offending generator in the rhs of *eqnptr */ if (i == 0) {
tmalloc(eqnptr[numeqns].rhs, gen, 1);
eqnptr[numeqns].rhs[0] = 0;
} else {
tmalloc(eqnptr[numeqns].rhs, gen, 2);
eqnptr[numeqns].rhs[0] = i;
eqnptr[numeqns].rhs[1] = 0;
}
numeqns++; if (kbm_print_level >= 3)
printf(" #Found offending word number %d.\n", numeqns);
if (numeqns >= maxeqns) {
tfree(definition);
tfree(occurs);
tfree(includes);
short_hash_clear(&ht); if (kbm_print_level >= 2)
printf(" #Found %d new equations. Aborting.\n", maxeqns); return numeqns;
}
} /* We have now checked that the new state is valid - *sorememberitsdefinition
*/
nsnew++; if (nsnew == maxv) { /* need room for more definitions */ if (kbm_print_level >= 3)
printf(" #Allocating more space for vertex definitions.\n");
tmalloc(newdef, struct vertexd, 2 * maxv); for (i = 1; i < maxv; i++)
newdef[i] = definition[i];
tfree(definition);
definition = newdef;
maxv *= 2;
}
definition[nsnew].g = g1;
definition[nsnew].state = cstate;
}
}
}
/* If we get to the end of the loop safely, then we have completed the *multipliercorrectnesscheckingtest.
*/
tfree(definition);
tfree(occurs);
tfree(includes);
short_hash_clear(&ht);
return numeqns;
}
/* If the checking fails, the failing word will be returned in the lhs of **eqnptr,andtheassociatedgeneratorintherhs.
*/ staticint fsa_checkmult_int(fsa *multptr, reduction_equation *eqnptr, int maxeqns, boolean cosets, int separator)
{ int **table, dr, ne, ngens, ngens1, ns, nsnew, bstate, numeqns, e, es, ef,
espad, efpad, cstate, cs, csi, i, j, g1, bg1, im, len; int *ht_ptr, *ht_chptr, *ht_ptrb, *ht_ptre, *cs_ptr, *cs_ptre, *ptr;
gen **genlist, *genptr;
boolean dense_ip, *occurs, *includes, got;
setToLabelsType *state_label;
hash_table ht; int maxv = 65536; struct vertexd {
gen g; int state;
} * definition, *newdef; /* This is used to store the defining transition for the states of the new *fsa.Ifdefinition[i]=v,thenstateiisdefinedbythetransitionfrom *statev.state,withgeneratorv.g. *State1doesnothaveadefinition.
*/
if (kbm_print_level >= 3)
printf(" #Calling fsa_checkmult_short.\n"); if (!multptr->flags[DFA]) {
fprintf(stderr, "Error: fsa_checkmult only applies to DFA's.\n"); return -1;
}
if (multptr->alphabet->type != PRODUCT || multptr->alphabet->arity != 2) {
fprintf(stderr, "Error in fsa_checkmult: fsa must be 2-variable.\n"); return -1;
} if (multptr->states->type != LABELED) {
fprintf(stderr, "Error in fsa_checkmult: states of fsa must be of labeled type.\n"); return -1;
}
/* We are not actually going to construct a new fsa - we just go through the *motionsofconstructingthehash-tablethatrepresentsitsstates.
*/
ne = multptr->alphabet->size;
ngens = multptr->alphabet->base->size;
ngens1 = ngens + 1;
state_label = multptr->states->setToLabels;
ns = multptr->states->size;
if (ne != ngens1 * ngens1 - 1) {
fprintf(stderr, "Error: in a 2-variable fsa, alphabet size should = " "(ngens+1)^2 - 1.\n"); return -1;
}
tmalloc(occurs, boolean, ngens + 1); for (i = 0; i <= ngens; i++)
occurs[i] = FALSE; for (i = 1; i <= ns; i++) if ((j = state_label[i])) {
genlist = multptr->states->labels->wordslist[j]; /* the list of words that is the label for state number *ptr */ while ((genptr = *(genlist++)))
occurs[genptr[0]] = TRUE;
}
hash_init(&ht, FALSE, 0, 0, 0);
ht_ptr = ht.current_ptr;
ht_ptr[0] = multptr->initial[1];
im = hash_locate(&ht, 1); /* Each state in the new fsa will be represented as a subset of the set of *states*of*multptr.Theinitialstateisone-elementsetcontaining *theinitialstateof*multptr. *Thesubsetswillbestoredasvariable-lengthrecordsinthehash-table, *alwaysinincreasingorder.
*/ if (im != 1) {
fprintf(stderr, "Hash-initialisation problem in fsa_checkmult.\n"); return -1;
}
/* Set up the array of structures to remember state-definitions. */
tmalloc(definition, struct vertexd, maxv);
nsnew = 1;
tmalloc(includes, boolean, ngens + 2); /* this will be used for checking validity of new states - *includes[ngens+1]isnotused,butmaybereferencedaccidentally
*/
cstate = 0;
numeqns = 0;
while (++cstate <= ht.num_recs) { if (kbm_print_level >= 3) { if ((cstate <= 1000 && cstate % 100 == 0) ||
(cstate <= 10000 && cstate % 1000 == 0) ||
(cstate <= 100000 && cstate % 5000 == 0) || cstate % 50000 == 0)
printf(" #cstate = %d; number of states = %d.\n", cstate,
ht.num_recs);
}
cs_ptr = hash_rec(&ht, cstate);
cs_ptre = hash_rec(&ht, cstate) + hash_rec_len(&ht, cstate) - 1; for (g1 = 1; g1 <= ngens; g1++) { /* Calculate action of generator g1 on state cstate - to get the image, *wehavetoapply(g1,g2)toeachelementinthesubsetcorrespondingto *cstate,andthisforeachgeneratorg2ofthebase-alphabet(including *thepaddingsymbol).
*/
ht_ptrb = ht.current_ptr;
ht_ptre = ht_ptrb - 1;
ptr = cs_ptr - 1;
es = (g1 - 1) * ngens1 + 1;
ef = g1 * ngens1; /* As g2 ranges from 1 to ngens+1 in the pair (g1,g2), for fixed g1, the *correspondingedgenumberinthefsarangesfromestoef.
*/
while (++ptr <= cs_ptre) {
cs = *ptr; for (e = es; e <= ef; e++) {
csi = target(dense_ip, table, e, cs, dr); if (csi == 0) continue; if (ht_ptrb > ht_ptre || csi > *ht_ptre) { /* We have a new state for the image subset to be added to the end
*/
*(++ht_ptre) = csi;
} else {
ht_chptr = ht_ptrb; while (*ht_chptr < csi)
ht_chptr++; if (csi < *ht_chptr) { /* we have a new state for the image subset to be added in the
* middle */
ht_ptr = ++ht_ptre; while (ht_ptr > ht_chptr) {
*ht_ptr = *(ht_ptr - 1);
ht_ptr--;
}
*ht_ptr = csi;
}
}
}
}
im = hash_locate(&ht, ht_ptre - ht_ptrb + 1); if (im == -1) return -1; if (im > nsnew) { /* We have a new state. We must check to see if it is valid - i.e. *containsanaccept-stateofeachmultiplier.Butfirstwehaveto *closeitundertheactionof($,g)forgeneratorsg.(Wecanput *extrastatesfoundattheend-thiswillnotdisturbthe *hash-table.)
*/
espad = ngens * ngens1 + 1;
efpad = ngens1 * ngens1 - 1;
ptr = ht_ptrb - 1; while (++ptr <= ht_ptre) {
cs = *ptr; for (e = espad; e <= efpad; e++) {
csi = target(dense_ip, table, e, cs, dr); if (csi == 0) continue; /* see if csi is new */
ht_chptr = ht_ptrb - 1;
got = FALSE; while (++ht_chptr < ht_ptre) if (csi == *ht_chptr) {
got = TRUE; break;
} if (!got) /* add csi to the end */
*(++ht_ptre) = csi;
}
} /* State is now closed under ($,g) - so check validity */ for (i = 0; i <= ngens; i++)
includes[i] = FALSE;
ptr = ht_ptrb - 1; while (++ptr <= ht_ptre) if ((j = state_label[*ptr])) {
genlist = multptr->states->labels->wordslist[j]; /* the list of words that is the label for state number *ptr */ while ((genptr = *(genlist++)))
includes[genptr[0]] = TRUE;
}
for (i = 0; i <= ngens; i++) if (occurs[i] && !includes[i]) { /* The state is invalid for generator number i. *Wereconstructtheoffendingwordw,usingthestate-definitions, *andthenabort.
*/ if (numeqns == 0 && kbm_print_level > 0)
printf("#Multiplier incorrect with generator number %d.\n", i); /* First see how long the word is */
len = 1;
bg1 = g1;
bstate = cstate; while (bstate != 1) {
len++;
bg1 = definition[bstate].g;
bstate = definition[bstate].state;
} /* Now allocate space for it - allow an extra place for multiplying *byagenerator. *Inthecosetscase,alsoanextraplacefortheseparator *thatweinsertatthebeginningoftheword.
*/ if (cosets)
len++;
tmalloc(eqnptr[numeqns].lhs, gen, len + 2);
eqnptr[numeqns].lhs[len] = 0;
bg1 = g1;
bstate = cstate; while (1) {
eqnptr[numeqns].lhs[--len] = bg1; if (bstate == 1) break;
bg1 = definition[bstate].g;
bstate = definition[bstate].state;
} if (cosets)
eqnptr[numeqns].lhs[--len] = separator; /* Put the offending generator in the rhs of *eqnptr */ if (i == 0) {
tmalloc(eqnptr[numeqns].rhs, gen, 1);
eqnptr[numeqns].rhs[0] = 0;
} else {
tmalloc(eqnptr[numeqns].rhs, gen, 2);
eqnptr[numeqns].rhs[0] = i;
eqnptr[numeqns].rhs[1] = 0;
}
numeqns++; if (kbm_print_level >= 3)
printf(" #Found offending word number %d.\n", numeqns);
if (numeqns >= maxeqns) {
tfree(definition);
tfree(occurs);
tfree(includes);
hash_clear(&ht); if (kbm_print_level >= 2)
printf(" #Found %d new equations. Aborting.\n", maxeqns); return numeqns;
}
} /* We have now checked that the new state is valid - *sorememberitsdefinition
*/
nsnew++; if (nsnew == maxv) { /* need room for more definitions */ if (kbm_print_level >= 3)
printf(" #Allocating more space for vertex definitions.\n");
tmalloc(newdef, struct vertexd, 2 * maxv); for (i = 1; i < maxv; i++)
newdef[i] = definition[i];
tfree(definition);
definition = newdef;
maxv *= 2;
}
definition[nsnew].g = g1;
definition[nsnew].state = cstate;
}
}
}
/* If we get to the end of the loop safely, then we have completed the *multipliercorrectnesscheckingtest.
*/
tfree(definition);
tfree(occurs);
tfree(includes);
hash_clear(&ht);
return numeqns;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet am 2026-06-18)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.