/* gpchecksubwa.c 22.4.96. * 31/12/98 change to deal with fact that subwa now has state type * labeled. * 26/10/98 large scale reorganisation to omit globals, etc. * 5/2/98 change generators from type char to type `gen'. * 6.5.97. corrected bug - not enough space allocated for storedmult. * Check the correctness of the subgroup word acceptor output by gpsubwa. * If incorrect, output some words in the subgroup that are not * accepted by the word accpetor, so that gpsubwa can use them on re-running. * * SYNOPSIS: * gpchecksubwa [-ip d/s[dr]] [-op d/s] [-silent] [-v] [-l] [-f] [-s] * [-m maxwords] groupname [subname] * * subname defaults to "sub". * autcos (or equaivalents) must already have been run on groupname. * groupname.subname should contain the definition of the subgroup, * in the standard format. * Input is from groupname.subname.wa and groupname.gm. * Output to (and input from) temporary files groupname.m* (for * multipliers) and groupname.subname.submult. * If word acceptor is wrong, output of original subgroup generators + * offending elements of subgroup to groupname.subname.words. * * OPTIONS: * -ip d/s[dr] input in dense or sparse format - dense is default * -op d/s output in dense or sparse format - sparse is default * -m maxwords Abort after finding maxwords offending words w * default is MAXWORDS * -v verbose * -silent no diagnostics * -l/-h large/huge hash-tables (for big examples) * -f read the transition table repeatedly from file while minimizing, * in calls of fsa_composite. * This avoids storing large tables, but is a little slower. * -s Throw away files immediately after use whenever possible, to * save disk-space. This will slow things down considerably.
*/
/* First read in the candidate for the subgroup automaton. */
sprintf(inf, "%s.%s.wa", gpname, subname); if ((rfile = fopen(inf, "r")) == 0) {
fprintf(stderr, "Cannot open file %s.\n", inf); exit(1);
}
fsa_read(rfile, &subwa, DENSE, 0, 0, TRUE, fsaname);
fclose(rfile); /* Since this now has states of type labeled, we need to remove this * structure, or fsa_equal will not work in the correctness test.
*/
srec_clear(subwa.states->labels);
tfree(subwa.states->labels);
tfree(subwa.states->setToLabels);
subwa.states->type = SIMPLE;
fsa_minimize(&subwa); if (kbm_print_level > 1)
printf(" #Number of states of subwa after minimisation = %d.\n",
subwa.states->size);
/* Now we read in the subgroup generators. */
sprintf(inf, "%s.%s", gpname, subname); if ((rfile = fopen(inf, "r")) == 0) {
fprintf(stderr, "Cannot open file %s.\n", inf); exit(1);
}
read_subgpgens();
fclose(rfile);
if (keepfiles) { /* Assign space for storedmult; storedmult[i] will be the file suffix where * the i-th multiplier automaton is stored.
*/
ct = nsubgens; for (i = 0; i < nsubgens; i++)
ct += 2 * genstrlen(subgen[i]);
tmalloc(storedmult, char *, ct);
numstoredmult = 0;
}
/* Now, for each subgroup generator, form the corresponding multiplier * automaton in the group, intersect its language with that of the * candidate subgroup word acceptor, and check its closure on multiplying * by that subgroup generator (on either side).
*/ for (i = 0; i < nsubgens; i++) { if (kbm_print_level > 0) {
kbm_buffer[0] = '\0';
add_to_buffer(0, "#Processing subgroup generator: ");
add_word_to_buffer(stdout, subgen[i], names);
printbuffer(stdout);
}
suff = file_suffix(subgen[i]);
gotsuff = FALSE; if (keepfiles) { /* Check to see if we have of this multiplier already */ for (j = 1; j <= numstoredmult; j++) { if (strcmp(suff, storedmult[j]) == 0)
gotsuff = TRUE;
}
} if (!gotsuff) { if (subgen_multiplier(subgen[i], suff) == -1) exit(1);
}
sprintf(inf, "%s.m%s", gpname, suff); if ((rfile = fopen(inf, "r")) == 0) {
fprintf(stderr, "Cannot open file %s.\n", inf); exit(1);
}
fsa_read(rfile, &mult, DENSE, 0, 0, TRUE, fsaname);
fclose(rfile); if (kbm_print_level > 1) {
printf(" #Number of states of multiplier = %d.\n", mult.states->size);
printf(" #Intersecting with candidate subgroup word-acceptor.\n");
}
submultptr =
fsa_submult(&subwa, &mult, op_store, FALSE, tempfilename, readback); if (submultptr == 0) exit(1);
fsa_clear(&mult); if (kbm_print_level > 1)
printf(" #Number of states of submultptr before minimisation = %d.\n",
submultptr->states->size); if (readback) { if (fsa_minimize(submultptr) == -1) exit(1);
} else { if (fsa_ip_minimize(submultptr) == -1) exit(1);
} if (kbm_print_level > 1)
printf(" #Number of states of submultptr after minimisation = %d.\n",
submultptr->states->size);
/* As usual, we output and input again, in case we want to change storage * types.
*/
base_prefix(fsaname);
strcat(fsaname, ".submult");
sprintf(outf, "%s.%s.submult", gpname, subname);
wfile = fopen(outf, "w");
fsa_print(wfile, submultptr, fsaname);
fclose(wfile);
fsa_clear(submultptr);
if ((rfile = fopen(outf, "r")) == 0) {
fprintf(stderr, "Cannot open file %s.\n", outf); exit(1);
}
fsa_read(rfile, submultptr, DENSE, 0, 0, TRUE, fsaname);
fclose(rfile); if (kbm_print_level > 1)
printf(" #Projecting onto left side.\n");
existsptr = fsa_exists(submultptr, op_store, FALSE, tempfilename); if (existsptr == 0) exit(1); if (kbm_print_level > 1)
printf( " #Number of states of left-projection before minimisation = %d.\n",
existsptr->states->size); if (fsa_minimize(existsptr) == -1) exit(1); if (kbm_print_level > 1)
printf( " #Number of states of left-projection after minimisation = %d.\n",
existsptr->states->size); if (!fsa_equal(&subwa, existsptr)) {
kbm_buffer[0] = '\0';
add_to_buffer(
0, "#Subgroup automaton check (on left) fails for generator: ");
add_word_to_buffer(stdout, subgen[i], names);
printbuffer(stdout);
tfree(submultptr);
unlink(outf); if (output_bad_words() == -1) exit(1); exit(2);
}
fsa_clear(existsptr);
tfree(existsptr);
if (kbm_print_level > 1)
printf(" #Projecting onto right side.\n"); if (fsa_swap_coords(submultptr) == -1) exit(1);
existsptr = fsa_exists(submultptr, op_store, TRUE, tempfilename); if (existsptr == 0) exit(1); if (kbm_print_level > 1)
printf( " #Number of states of right-projection before minimisation = %d.\n",
existsptr->states->size); if (fsa_minimize(existsptr) == -1) exit(1); if (kbm_print_level > 1)
printf( " #Number of states of right-projection after minimisation = %d.\n",
existsptr->states->size); if (!fsa_equal(&subwa, existsptr)) {
kbm_buffer[0] = '\0';
add_to_buffer(
0, "#Subgroup automaton check (on right) fails for generator: ");
add_word_to_buffer(stdout, subgen[i], names);
printbuffer(stdout);
tfree(submultptr);
unlink(outf); if (output_bad_words() == -1) exit(1); exit(2);
}
fsa_clear(existsptr);
tfree(existsptr);
tfree(submultptr);
unlink(outf);
for (i = 0; i < nsubgens; i++)
tfree(subgen[i]);
fsa_clear(&subwa);
tfree(badwords); if (keepfiles) { for (i = 1; i <= numstoredmult; i++) {
sprintf(outf, "%s.m%s", gpname, storedmult[i]);
unlink(outf);
tfree(storedmult[i]);
}
tfree(storedmult);
} if (kbm_print_level > 0)
printf("#Subgroup automata validity checking succeeded.\n"); exit(0);
}
/* For a word w in the generators, this function returns a corresponding * string with the terms of w replaced by integers separated by '_'. * This is used as a suffix in the filenames used for storing the * corresponding multiplier fsa's.
*/ char *file_suffix(gen *w)
{ char *s;
gen *p;
boolean first; int len; /* First work out the length of the required string. */
len = genstrlen(w);
p = w - 1; while (*(++p) != 0)
len += int_len((int)(*p));
tmalloc(s, char, len);
s[0] = '\0';
first = TRUE;
p = w - 1; while (*(++p) != 0) { if (first)
first = FALSE; else
sprintf(s + stringlen(s), "_");
sprintf(s + stringlen(s), "%d", *p);
} return s;
}
/* Calculate the multiplier associated with the word w. * s is the suffix of the file in which it will be stored. * (s has been derived from w by a call of file_suffix).
*/ int subgen_multiplier(gen *w, char *s)
{ int i, l;
gen *wl, *wlt, *wr, *wrt; char *suffl, *sufflt, *suffr, *suffrt;
boolean gotl, gotr, gotlt, gotrt; if (kbm_print_level >= 3) {
kbm_buffer[0] = '\0';
add_to_buffer(0, " #Calculating multiplier for word: ");
add_word_to_buffer(stdout, w, names);
printbuffer(stdout);
}
l = genstrlen(w);
if (l == 1) { /* Length 1 - use fsa_makemult */
strcpy(inf, gpname);
strcat(inf, ".gm"); if ((rfile = fopen(inf, "r")) == 0) {
fprintf(stderr, "Cannot open file %s.\n", inf); exit(1);
}
fsa_read(rfile, &genmult, op_store, 0, 0, TRUE, fsaname);
fclose(rfile); if (fsa_makemult(&genmult, w[0]) == -1) return -1; if (fsa_minimize(&genmult) == -1) return -1;
sprintf(outf, "%s.m%s", gpname, s);
wfile = fopen(outf, "w");
fsa_print(wfile, &genmult, fsaname);
fclose(wfile);
fsa_clear(&genmult);
} else { /* general case - we have to split w up */ if (l % 2 == 0) {
tmalloc(wl, gen, l / 2 + 1);
tmalloc(wr, gen, l / 2 + 1); for (i = 0; i < l / 2; i++)
wl[i] = w[i];
wl[l / 2] = '\0';
genstrcpy(wr, w + l / 2);
suffl = file_suffix(wl);
suffr = file_suffix(wr);
} else {
tmalloc(wl, gen, l / 2 + 2);
tmalloc(wr, gen, l / 2 + 1); for (i = 0; i <= l / 2; i++)
wl[i] = w[i];
wl[l / 2 + 1] = '\0';
genstrcpy(wr, w + l / 2 + 1);
suffl = file_suffix(wl);
suffr = file_suffix(wr);
} /* See whether we have either of them already */
gotl = gotr = FALSE; if (keepfiles) { for (i = 1; i <= numstoredmult; i++) { if (strcmp(suffl, storedmult[i]) == 0)
gotl = TRUE; if (strcmp(suffr, storedmult[i]) == 0)
gotr = TRUE;
}
}
if (keepfiles && l % 2 == 1 && (!gotl || !gotr)) { /* In this case, there are two possible ways to split w up - * we see if the other way has more multipliers already stored.
*/
tmalloc(wlt, gen, l / 2 + 1);
tmalloc(wrt, gen, l / 2 + 2); for (i = 0; i < l / 2; i++)
wlt[i] = w[i];
wlt[l / 2] = '\0';
genstrcpy(wrt, w + l / 2);
sufflt = file_suffix(wlt);
suffrt = file_suffix(wrt);
gotlt = gotrt = FALSE; for (i = 1; i <= numstoredmult; i++) { if (strcmp(sufflt, storedmult[i]) == 0)
gotlt = TRUE; if (strcmp(suffrt, storedmult[i]) == 0)
gotrt = TRUE;
} if ((gotlt && gotrt) || ((gotlt || gotrt) && !gotl && !gotr)) {
tfree(wl);
tfree(wr);
tfree(suffl);
tfree(suffr);
wl = wlt;
wr = wrt;
suffl = sufflt;
suffr = suffrt;
gotl = gotlt;
gotr = gotrt;
} else {
tfree(wlt);
tfree(wrt);
tfree(sufflt);
tfree(suffrt);
}
} if (!gotl) { if (subgen_multiplier(wl, suffl) == -1) return -1;
} if (!gotr && genstrcmp(wl, wr) != 0) { if (keepfiles) { /* Check again to see if we have got it recently */ for (i = 1; i <= numstoredmult; i++) if (strcmp(suffr, storedmult[i]) == 0)
gotr = TRUE;
} if (!gotr) { if (subgen_multiplier(wr, suffr) == -1) return -1;
}
} /* Read back in the two multipliers and form their composite */
sprintf(inf, "%s.m%s", gpname, suffl); if ((rfile = fopen(inf, "r")) == 0) {
fprintf(stderr, "Cannot open file %s.\n", inf); exit(1);
}
fsa_read(rfile, &mult1, ip_store, dr, 0, TRUE, fsaname);
fclose(rfile);
sprintf(inf, "%s.m%s", gpname, suffr); if ((rfile = fopen(inf, "r")) == 0) {
fprintf(stderr, "Cannot open file %s.\n", inf); exit(1);
}
fsa_read(rfile, &mult2, ip_store, dr, 0, TRUE, fsaname);
fclose(rfile);
/* Read subgroup generators from rfile (assumed to be already open) */ void read_subgpgens(void)
{
nsubgens = 0;
read_ident(rfile, kbm_buffer, &delim, FALSE); /* this is the name of the record containing the subgenerators */ if (delim != ':') {
fprintf(stderr, "#Input error: file must contain a record assignment\n"); exit(1);
}
check_next_char(rfile, '=');
read_ident(rfile, kbm_buffer, &delim, FALSE); if (delim != '(' || strcmp(kbm_buffer, "rec") != 0) {
fprintf(stderr, "#Input error: file must contain a record assignment\n"); exit(1);
}
read_ident(rfile, kbm_buffer, &delim, FALSE); if (strcmp(kbm_buffer, "subGenerators") != 0) {
fprintf(stderr, "Input error. 'subGenerators' list expected in subgroup " "generator file.\n"); exit(1);
} if (delim != ':') {
fprintf(stderr, "#Input error: bad 'subgens' list assignment\n"); exit(1);
}
check_next_char(rfile, '=');
check_next_char(rfile, '[');
nsubgens = 0; do { if (!read_word(rfile, testword, testword + maxwordlen, &delim, names, ngens, TRUE)) {
fprintf(stderr, "#Input error: no subgroup generators or missing word.\n"); exit(1);
} if (nsubgens + 1 > maxsubgens) {
fprintf(stderr, "#Input error: too many subgroup generators.\n"); exit(1);
}
tmalloc(subgen[nsubgens], gen, genstrlen(testword) + 1);
genstrcpy(subgen[nsubgens], testword);
nsubgens++;
} while (delim != ']');
}
/* *existsptr and subwa are unequal. We need to find some words accepted * by subwa but not by *existsptr. * The function words_and_not will do this. * We then output the words, along with the original subgroup generators, * so that they can be used in the next run of gpsubwa.
*/ int output_bad_words(void)
{ int numwords, i;
tmalloc(badwords, gen *, maxwords) numwords =
words_and_not(&subwa, existsptr, badwords, maxwords); if (numwords == -1) return -1; if (numwords == 0) {
fprintf(stderr, "Error: No offending subwords found!\n"); return -1;
}
sprintf(outf, "%s.%s.words", gpname, subname); /* We first see if there is already a list of words in the output file. * If so, then we want to include them as well in the new output.
*/
rfile = fopen(outf, "r"); if (rfile) { /* We replace out existing list of subgroup generators with the one in this * file
*/ for (i = 0; i < nsubgens; i++)
tfree(subgen[i]) read_subgpgens();
fclose(rfile);
} if (kbm_print_level > 0)
printf(" #Outputting %d subgroup generators + %d offending words.\n",
nsubgens, numwords);
wfile = fopen(outf, "w");
fprintf(wfile, "_RWS_Sub_words := rec(\n subGenerators:=[\n"); /* First write the original subgroup generators */ for (i = 0; i < nsubgens; i++) {
kbm_buffer[0] = '\0';
add_to_buffer(4, "");
add_word_to_buffer(wfile, subgen[i], names);
add_to_buffer(0, ",");
printbuffer(wfile);
tfree(subgen[i]);
} /* And now the offending words */ for (i = 0; i < numwords; i++) {
kbm_buffer[0] = '\0';
add_to_buffer(4, "");
add_word_to_buffer(wfile, badwords[i], names); if (i != numwords - 1)
add_to_buffer(0, ",");
printbuffer(wfile);
tfree(badwords[i]);
}
fprintf(wfile, " ];\n);\n");
fclose(wfile);
fsa_clear(existsptr);
tfree(existsptr);
tfree(badwords);
fsa_clear(&subwa); return 0;
}
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.