int (*reduce_word)(gen *w, reduction_struct *rs_rws); /* The word-reduction *function-itcanbe *anyofrws_reduce, *slow_rws_reduce, *slow_rws_reduce_rk.
*/
boolean (*check_reduce_word)(gen *w, int i, rewriting_system *rwsptr); /* The functionthat checks if a word is reduced. *slow_check_rws_reduceorslow_check_rws_reduce_rk
*/
/* Functions defined in this file: */ staticvoid build_fulltable(rewriting_system *rwsptr); int check_finite(rewriting_system *rwsptr, int max); int compare(gen *w1, gen *w2, rewriting_system *rwsptr); int conf_check(rewriting_system *rwsptr); void consider(int k, int l, rewriting_system *rwsptr); int tidyup(int crelno, rewriting_system *rwsptr); int type_sort_eqns(int x, rewriting_system *rwsptr); int wd_sort_eqns(int x, rewriting_system *rwsptr);
int kbprog(rewriting_system *rwsptr)
{ int i, j, k, l, cct, onum_eqns, onum_eqnsi;
reduction_struct rs_rws;
rs_rws.rws = rwsptr;
rs_rws.separator = rwsptr->separator;
/* The general policy is that *wheneveranewrelationisfound,itisimmediatelycomparedwith *alloftheinverserelations.Thisseemstobemostefficient.It *mightalsobeagoodideatoimmediatelycomparenewrelations *withanyotherveryshortrelations.Otherwise,anewrelationhas *towaitinthequeuebeforebeingcomparedwiththeothers.
*/
rwsptr->tidyon = rwsptr->tidyon_now = FALSE;
tmalloc(rwsptr->history, int, rwsptr->maxreducelen);
tmalloc(rwsptr->slowhistory, int *, rwsptr->maxreducelen);
tmalloc(rwsptr->slowhistorysp, int, rwsptr->maxslowhistoryspace);
if (rwsptr->print_eqns) for (k = 1; k <= rwsptr->num_eqns; k++) {
printf(" #Initial equation number %d:\n", k);
*kbm_buffer = '\0';
add_to_buffer(6, "#");
l = add_word_to_buffer(stdout, rwsptr->eqns[k].lhs, rwsptr->gen_name);
sprintf(kbm_buffer + strlen(kbm_buffer), " -> "); if (l > 0 || strlen(kbm_buffer) > 40) {
printbuffer(stdout);
add_to_buffer(8, "");
}
add_word_to_buffer(stdout, rwsptr->eqns[k].rhs, rwsptr->gen_name);
printbuffer(stdout);
}
reduce_word = slow_rws_reduce;
check_reduce_word = slow_check_rws_reduce; if (rwsptr->num_eqns == rwsptr->maxeqns) {
rwsptr->tidyon = TRUE;
rwsptr->tidyon_now = TRUE;
kbm_onintr = TRUE;
} else for (k = rwsptr->num_inveqns + 1; k <= rwsptr->num_eqns; k++) { for (l = 1; l <= rwsptr->num_inveqns; l++) {
consider(k, l, rwsptr); if (rwsptr->exit_status == 1) return0; if (rwsptr->tidyon_now) break;
consider(l, k, rwsptr); if (rwsptr->exit_status == 1) return0; if (rwsptr->tidyon_now) break;
} if (rwsptr->tidyon_now) break;
}
if (kbm_onintr)
rwsptr->tidyon = rwsptr->tidyon_now = TRUE; /* When tidy_on becomes true, we are due to tidy up, but we deal with *overlapswithinverseequationsfirst-thiscanavoidanexcessive *numberofword-differenceswhichlaterturnouttoberedundant. *However,iftidy_on_nowbecomestrue,wehavetoomanynewequations, *andwetidyupimmediately.
*/
restart:
rwsptr->nneweqns = 0;
cct = 0; for (i = rwsptr->num_inveqns + 1; i <= rwsptr->num_eqns; i++) {
onum_eqnsi = rwsptr->num_eqns; for (j = 1; j <= i; j++) { if (rwsptr->eqns[i].done && rwsptr->eqns[j].done) continue; if (rwsptr->tidyon) break; /* only there for when i = 1 */
cct++;
onum_eqns = rwsptr->num_eqns;
consider(i, j, rwsptr); if (rwsptr->exit_status == 1) return0; if (rwsptr->tidyon_now) break; if (i != j)
consider(j, i, rwsptr); if (rwsptr->exit_status == 1) return0; if (rwsptr->tidyon_now) break; if (rwsptr->num_eqns > onum_eqns) /* Compare new relations with inverse
* relations */ for (k = onum_eqns + 1; k <= rwsptr->num_eqns; k++) { for (l = 1; l <= rwsptr->num_inveqns; l++) {
consider(k, l, rwsptr); if (rwsptr->exit_status == 1) return0; if (rwsptr->tidyon_now) break;
consider(l, k, rwsptr); if (rwsptr->exit_status == 1) return0; if (rwsptr->tidyon_now) break;
} if (rwsptr->tidyon_now) break;
} if (rwsptr->tidyon) break;
} /* If we have more than rwsptr->tidyint new relations since last *tidyingup,thentidy;thatis,gothroughallrelations, *removetheredundantones,andthenredefinetheFSA.This
* will usually reduce its number of states. */ if (kbm_onintr) {
rwsptr->halting = rwsptr->tidyon = TRUE;
rwsptr->exit_status = 2;
} if (rwsptr->tidyon) {
i = tidyup(i, rwsptr) - 1; if (rwsptr->exit_status == 1) return0; if (rwsptr->cosets && rwsptr->finitestop) {
build_fulltable(rwsptr);
k = check_finite(rwsptr, 128); if (k) {
printf("#Coset language has size %d.", k);
rwsptr->maxoverlaplen =
rwsptr->maxcosetlen + rwsptr->maxlhsrellen > rwsptr->maxsubgenlen
? rwsptr->maxcosetlen + rwsptr->maxlhsrellen
: rwsptr->maxsubgenlen;
printf(" Setting rws.maxoverlap length to %d.\n",
rwsptr->maxoverlaplen);
}
build_quicktable(rwsptr);
} if (rwsptr->halting) { if (!rwsptr->worddiffs) {
build_fulltable(rwsptr);
reduce_word = rws_reduce;
} return0;
} if (rwsptr->worddiffs) { if (rwsptr->wd_reorder)
tmalloc(rwsptr->new_wd, boolean,
rwsptr->num_eqns + 1) else rwsptr->new_wd = 0; if (rwsptr->cosets) { if (build_wd_fsa_cos(rwsptr->wd_fsa, rwsptr->new_wd, &rs_rws) == -1) {
rwsptr->exit_status = 1; return0;
}
} else { if (build_wd_fsa(rwsptr->wd_fsa, rwsptr->new_wd, &rs_rws) == -1) {
rwsptr->exit_status = 1; return0;
}
}
should_we_halt(rwsptr); if (rwsptr->halting) return0; if (rwsptr->wd_fsa->states->size > rwsptr->maxwdiffs / 2) {
gen **newwords; if (kbm_print_level > 2 && kbm_print_level % 3 == 0)
printf(" #Increasing rwsptr->maxwdiffs to %d.\n",
rwsptr->maxwdiffs * 2);
rwsptr->maxwdiffs *= 2;
tmalloc(newwords, gen *, rwsptr->maxwdiffs + 1); for (j = 1; j <= rwsptr->wd_fsa->states->size; j++)
newwords[j] = rwsptr->wd_fsa->states->words[j];
tfree(rwsptr->wd_fsa->states->words);
rwsptr->wd_fsa->states->words = newwords;
tfree(rwsptr->wd_fsa->table->table_data_ptr[0]);
tfree(rwsptr->wd_fsa->table->table_data_ptr);
fsa_table_init(rwsptr->wd_fsa->table, rwsptr->maxwdiffs,
rwsptr->wd_fsa->alphabet->size);
tfree(rwsptr->wd_fsa->table->table_data_dptr); if (fsa_table_dptr_init(rwsptr->wd_fsa) == -1) return -1;
}
clear_wd_fsa(rwsptr->wd_fsa); if (rwsptr->wd_reorder) {
i = wd_sort_eqns(i, rwsptr) - 1;
tfree(rwsptr->new_wd);
}
} elseif (rwsptr->cosets)
i = type_sort_eqns(i, rwsptr) - 1;
rwsptr->tidyon = rwsptr->tidyon_now = FALSE;
rwsptr->nneweqns = 0;
} elseif (onum_eqnsi == rwsptr->num_eqns) { /* Number of equations has not increased for this i.
*/ if (rwsptr->confnum > 0 && cct >= rwsptr->confnum) {
rwsptr->do_conf_test = TRUE;
i = tidyup(i, rwsptr); if (rwsptr->exit_status == 1) return0; if (kbm_print_level >= 2)
printf(" #No new eqns for some time - testing for confluence\n");
k = conf_check(rwsptr); if (rwsptr->exit_status == 1) return0; if (k == 1) { if (rwsptr->hadlongoverlap && kbm_print_level > 0) {
printf("#System is not guaranteed confluent, since not all " "overlaps were processed.\n");
} elseif (rwsptr->cosets && !rwsptr->Hoverlaps &&
kbm_print_level > 0) {
printf("#System is not guaranteed confluent, as no subgroup " "overlaps were processed.\n");
} else { if (kbm_print_level > 0)
printf("#System is confluent.\n");
rwsptr->confluent = TRUE;
} return0;
} elseif (k == -1) { if (kbm_print_level > 0)
printf("#System is not confluent - halting because new equations " "are too long.\n"); return0;
} elseif (rwsptr->halting) return0;
rwsptr->do_conf_test = FALSE;
cct = 0;
} elseif (rwsptr->rk_on && rwsptr->oldconfnum > 0 &&
cct >= 8 * rwsptr->oldconfnum) { if (kbm_print_level >= 2)
printf(" #No new eqns for some time - will tidy up\n");
rwsptr->tidyon = TRUE;
cct = 0;
}
} else
cct = 0;
rwsptr->eqns[i].done = TRUE;
}
/* Algorithm has now completed. */ if (kbm_print_level >= 2)
printf(" #Search for overlaps is complete.\n");
rwsptr->halting = TRUE;
tidyup(rwsptr->num_eqns, rwsptr); if (rwsptr->exit_status == 1) return0;
k = conf_check(rwsptr); if (rwsptr->exit_status == 1) return0; if (k == 1) { if (rwsptr->hadlongoverlap && kbm_print_level > 0) {
printf("#System is not guaranteed confluent, since not all overlaps were " "processed.\n");
} elseif (rwsptr->cosets && !rwsptr->Hoverlaps && kbm_print_level > 0) {
printf("#System is not guaranteed confluent, as no subgroup overlaps " "were processed.\n");
} else { if (kbm_print_level > 0)
printf("#System is confluent.\n");
rwsptr->confluent = TRUE;
}
} elseif (k == -1 && kbm_print_level > 0)
printf("#System is not confluent - halting because new equations are too " "long.\n"); elseif (k == 0) {
printf("#Search for overlaps is complete, but system is not confluent.\n"); if (!kbm_onintr) {
printf("#Let's try again then!\n");
rwsptr->halting = FALSE;
build_quicktable(rwsptr);
reduce_word = slow_rws_reduce; goto restart;
}
} return0;
}
/* Look at the words in rwsptr->testword1 and rwsptr->testword2, and remove any *commonprefixesandsuffixesofgeneratorswithinverses. *Iftheyarenotbothemptyatthatstage,thenuseprocedure *"compare"toseewhichwordcomesfirstintheordering. *Ifusingshortlexorder,andlength(bigger)-length(smaller)>2,then *useinversesofgeneratorstotransfergeneratorsfromtestword1to *testword2.Finally,copytestword1andtestword2into*lhs,and*rhs *(afterassigningspace). *Returnvalueis0iflhsandrhsareequal,1ifthenewequationis *inserted,and-1ifitisnotinsertedbecauseitistoolong *accordingtomaxlenleftandmaxlenright.
*/ int insert(gen **lhs, gen **rhs, rewriting_system *rwsptr)
{ int bigger;
gen *ptr1, *ptr2, *t1, *t2, *ts, *ptre1, *ptre2, *u1, *u2, *ptrc2a, *ptrc2b; int *inv = rwsptr->inv_of;
/* t1 is biggest according to the ordering, so it becomes the LHS of *thenewrelation.
*/
tmalloc(*lhs, gen, genstrlen(t1) + 1) ptr1 = t1;
ptr2 = *lhs; while (ptr1 < ptre1)
*(ptr2++) = *(ptr1++);
*(ptr2++) = '\0';
tmalloc(*rhs, gen, genstrlen(t2) + 1) ptr1 = t2;
ptr2 = *rhs; while (ptr1 < ptre2)
*(ptr2++) = *(ptr1++);
*(ptr2++) = '\0';
return1;
}
/* The left hand sides of the relations k and l are considered for common *parts,accordingtotheKnuth-Bendixprocedure,andanynewrelations *producedareprocessed. *Welookforoverlapsofeitherasuffixofequationkwithaprefixof *equationl,orofasubwordofeqn.kwiththewholeofeqn.l.
*/ void consider(int k, int l, rewriting_system *rwsptr)
{
gen *midwd, *ptr1, *ptr2, *ptr, *testwd1, *testwd2;
boolean ok;
gen *tw1 = rwsptr->testword1, *tw2 = rwsptr->testword2; int mol = rwsptr->maxoverlaplen; int ne1; int r, n, pl;
reduction_struct rs_rws;
rs_rws.rws = rwsptr;
rs_rws.separator = rwsptr->separator;
testwd1 = rwsptr->eqns[k].lhs;
testwd2 = rwsptr->eqns[l].lhs; if (rwsptr->cosets && !rwsptr->Hoverlaps &&
(Hgen(testwd1[genstrlen(testwd1) - 1]) ||
Hgen(testwd2[genstrlen(testwd2) - 1]))) return;
midwd = testwd1;
pl = 0; if (rwsptr->cosets) { while (*midwd != '\0') { if (*midwd == rwsptr->separator) {
pl = midwd - testwd1 + 1; /* the subgroup prefix length */ break;
}
midwd++;
}
}
midwd = testwd1; while (*midwd != '\0') {
ne1 = rwsptr->num_eqns + 1; if (mol > 0 && (midwd - testwd1 - pl) + genstrlen(testwd2) > mol) { /* Any further overlap would exceed the permitted length */ break;
}
ptr1 = midwd;
ptr2 = testwd2;
ok = TRUE; while (*ptr1 != '\0' && *ptr2 != '\0') { if (*ptr1 != *ptr2) {
ok = FALSE; break;
}
ptr1++;
ptr2++;
} if (ok) /* An overlap has been found. The new equation *forconsiderationisinsertedintowords
* rwsptr->testword1 and rwsptr->testword2. */
{ if (*ptr1 == '\0') {
ptr1 = testwd1 - 1;
ptr = tw1 - 1; while (++ptr1 < midwd)
*(++ptr) = *ptr1;
ptr1 = rwsptr->eqns[l].rhs - 1; while (*(++ptr1) != '\0')
*(++ptr) = *ptr1;
*(++ptr) = '\0';
ptr1 = rwsptr->eqns[k].rhs - 1;
ptr = tw2 - 1; while (*(++ptr1) != '\0')
*(++ptr) = *ptr1;
ptr1 = ptr2 - 1; while (*(++ptr1) != '\0')
*(++ptr) = *ptr1;
*(++ptr) = '\0';
} else {
ptr2 = testwd1 - 1;
ptr = tw1 - 1; while (++ptr2 < midwd)
*(++ptr) = *ptr2;
ptr2 = rwsptr->eqns[l].rhs - 1; while (*(++ptr2) != '\0')
*(++ptr) = *ptr2;
ptr2 = ptr1 - 1; while (*(++ptr2) != '\0')
*(++ptr) = *ptr2;
*(++ptr) = '\0';
ptr2 = rwsptr->eqns[k].rhs - 1;
ptr = tw2 - 1; while (*(++ptr2) != '\0')
*(++ptr) = *ptr2;
*(++ptr) = '\0';
} /* Now reduce rwsptr->testword1 and rwsptr->testword2, *usingthecurrentrelations,andtheninstall
* them if they are different. */ if (reduce_word(tw1, &rs_rws) == -1) {
rwsptr->exit_status = 1; return;
} if (reduce_word(tw2, &rs_rws) == -1) {
rwsptr->exit_status = 1; return;
} if (genstrlen(tw1) <= rwsptr->maxreducelen / 2 &&
genstrlen(tw2) <= rwsptr->maxreducelen / 2 &&
insert(&(rwsptr->eqns[ne1].lhs), &(rwsptr->eqns[ne1].rhs), rwsptr) > 0) { /* We have a new equation */ if (rwsptr->print_eqns) {
printf(" #New equation number %d, from overlap %d, %d:\n", ne1, k,
l);
*kbm_buffer = '\0';
add_to_buffer(6, "#");
n = add_word_to_buffer(stdout, rwsptr->eqns[ne1].lhs,
rwsptr->gen_name);
sprintf(kbm_buffer + strlen(kbm_buffer), "->"); if (n > 0 || strlen(kbm_buffer) > 40) {
printbuffer(stdout);
add_to_buffer(8, "");
}
add_word_to_buffer(stdout, rwsptr->eqns[ne1].rhs, rwsptr->gen_name);
printbuffer(stdout);
}
r = modify_table(ne1, rwsptr); if (r == -1) {
tfree(rwsptr->eqns[ne1].lhs) tfree(rwsptr->eqns[ne1].rhs) return;
} if (r == 1) {
rwsptr->num_eqns++;
rwsptr->tot_eqns++;
rwsptr->eqns[ne1].done = FALSE; if (ne1 >= rwsptr->maxeqns) { if (kbm_print_level > 0)
printf("#Maximum number of equations exceeded.\n");
rwsptr->hadmaxeqns = TRUE;
rwsptr->hadct++;
rwsptr->tidyon = rwsptr->tidyon_now = TRUE; if (!rwsptr->worddiffs || rwsptr->hadct > rwsptr->maxhad) {
rwsptr->halting = TRUE;
rwsptr->exit_status = 2;
} /* If we are calculating word-differences we do not *alwaysneedtostop.
*/ return;
} /* Decide if it is time to tidy up. */ if (++rwsptr->nneweqns == rwsptr->tidyint)
rwsptr->tidyon = TRUE; if (rwsptr->nneweqns == 2 * rwsptr->tidyint)
rwsptr->tidyon_now = TRUE;
}
}
}
midwd++;
}
}
/* Remove redundant relations. "crelno" is the current relation being *processed. *Returnvalueisthenewvalueofcrelno,whichmayhavechangedas *aresultofearlierequationsbeingeliminated.
*/ int tidyup(int crelno, rewriting_system *rwsptr)
{ int i, iv, nnum_eqns, lenl, lenr, totlenl, totlenr, maxlenl, maxlenr, ret;
boolean moving, retain, red, some_changed;
gen **newlhs, **newrhs, *testword1 = rwsptr->testword1,
*testword2 = rwsptr->testword2;
reduction_equation **eqn = &(rwsptr->eqns);
reduction_struct rs_rws;
rs_rws.rws = rwsptr;
rs_rws.separator = rwsptr->separator;
ret = crelno;
repeat:
tmalloc(newlhs, gen *, rwsptr->num_eqns + 1)
tmalloc(newrhs, gen *, rwsptr->num_eqns + 1) for (i = 1;
i <= rwsptr->num_eqns;
i++)(*eqn)[i]
.changed = (*eqn)[i].eliminated = FALSE;
nnum_eqns = 0;
moving = FALSE;
some_changed = FALSE;
totlenl = totlenr = 0;
maxlenl = maxlenr = 0; for (i = 1; i <= rwsptr->num_eqns; i++) {
genstrcpy(testword1, (*eqn)[i].lhs);
genstrcpy(testword2, (*eqn)[i].rhs);
iv = 0;
red = check_reduce_word(testword1, i, rwsptr); if (red) { /* LHS is irreducible by other (*eqn) */
retain = TRUE; if (reduce_word(testword2, &rs_rws) == -1) {
rwsptr->exit_status = 1; return -1;
} if (genstrlen(testword2) > rwsptr->maxreducelen / 2)
iv = -1; if (genstrcmp(testword2, (*eqn)[i].rhs)) { /* RHS is reducible */
some_changed = (*eqn)[i].changed = TRUE;
(*eqn)[i].done = FALSE;
}
} else { /* LHS can be reduced using other equations */ if (reduce_word(testword1, &rs_rws) == -1) {
rwsptr->exit_status = 1; return -1;
} if (reduce_word(testword2, &rs_rws) == -1) {
rwsptr->exit_status = 1; return -1;
} if (genstrlen(testword1) > rwsptr->maxreducelen / 2 ||
genstrlen(testword2) > rwsptr->maxreducelen / 2)
iv = -1;
retain = genstrcmp(testword1, testword2); if (retain) {
some_changed = (*eqn)[i].changed = TRUE;
(*eqn)[i].done = FALSE;
}
} if ((*eqn)[i].changed) { if (iv == 0)
iv = insert(newlhs + i, newrhs + i, rwsptr);
retain = iv > 0; if (iv < 0)
rwsptr->lostinfo = TRUE;
} if (retain) {
lenl = genstrlen(testword1);
lenr = genstrlen(testword2);
totlenl += lenl;
totlenr += lenr; if (lenl > maxlenl)
maxlenl = lenl; if (lenr > maxlenr)
maxlenr = lenr;
} else {
moving = TRUE;
(*eqn)[i].eliminated = TRUE;
}
} if (moving || some_changed) {
moving = FALSE; for (i = 1; i <= rwsptr->num_eqns; i++) if (!(*eqn)[i].eliminated) {
nnum_eqns++; if ((*eqn)[i].changed) {
fflush(stdout);
tfree((*eqn)[i].lhs) tfree((*eqn)[i].rhs)(*eqn)[i].lhs = newlhs[i];
(*eqn)[i].rhs = newrhs[i];
} if (moving) /* "moving" means that some previous *relationshavenotbeenretained,
* and so we have to renumber words. */
{
fflush(stdout);
(*eqn)[nnum_eqns].lhs = (*eqn)[i].lhs;
(*eqn)[nnum_eqns].rhs = (*eqn)[i].rhs;
(*eqn)[nnum_eqns].done = (*eqn)[i].done;
(*eqn)[i].lhs = (*eqn)[i].rhs = 0;
(*eqn)[i].done = FALSE;
} if (i <= crelno)
ret = nnum_eqns;
} else {
moving = TRUE; if (i <= rwsptr->num_inveqns)
rwsptr->num_inveqns--;
fflush(stdout);
tfree((*eqn)[i].lhs) tfree((*eqn)[i].rhs)
}
} else
nnum_eqns = rwsptr->num_eqns; /* If any relations have been changed or eliminated, then we *completelyreconstructtheFSAfromscratch. *Thisisnottootimeconsumingprovidedthatwedonot *tidyuptoooften.
*/ if (rwsptr->num_states > rwsptr->current_maxstates) { /* shouldn't happen */ if (kbm_print_level > 0)
printf("#Maximum number of states exceeded (why?).\n");
rwsptr->halting = TRUE;
rwsptr->exit_status = 2;
}
tfree(newlhs) tfree(newrhs) if (moving || some_changed || rwsptr->rk_on)
{
rwsptr->tot_eqns -= (rwsptr->num_eqns - nnum_eqns);
rwsptr->num_eqns = nnum_eqns; if (rwsptr->rkmineqns > 0) { if (!rwsptr->rk_on && !rwsptr->halting &&
rwsptr->num_eqns >= rwsptr->rkmineqns) {
rwsptr->rk_on = TRUE;
reduce_word = slow_rws_reduce_rk;
check_reduce_word = slow_check_rws_reduce_rk;
rwsptr->oldconfnum = rwsptr->confnum;
rwsptr->confnum = 0; if (rk_init(rwsptr) == -1) {
rwsptr->exit_status = 1; return -1;
}
} elseif (rwsptr->rk_on && (rwsptr->num_eqns < rwsptr->rkmineqns ||
(rwsptr->halting && !rwsptr->worddiffs))) {
rwsptr->rk_on = FALSE;
reduce_word = slow_rws_reduce;
check_reduce_word = slow_check_rws_reduce;
rwsptr->confnum = rwsptr->oldconfnum;
rk_clear(rwsptr);
}
}
build_quicktable(rwsptr); /* On the last time, we need to be certain that the set of equations is *reduced,sowerepeat.
*/ if (rwsptr->finitestop || rwsptr->halting || rwsptr->do_conf_test) goto repeat;
} if (rwsptr->double_states)
build_quicktable(rwsptr); /* otherwise maxstates won't get doubled! */ struct rusage tmp;
getrusage(RUSAGE_SELF, &tmp);
i = tmp.ru_utime.tv_sec; if (kbm_print_level >= 2)
printf(" #%d eqns; total len: lhs, rhs = %d, %d; %d states; %d secs.\n",
rwsptr->num_eqns, totlenl, totlenr, rwsptr->num_states, i); if (kbm_print_level >= 3)
printf(" max len: lhs, rhs = %d, %d.\n", maxlenl, maxlenr);
return ret;
}
void build_quicktable(rewriting_system *rwsptr)
{ int i; int **table;
restart: if (rwsptr->double_states) {
rwsptr->current_maxstates *= 2;
tfree(rwsptr->reduction_fsa->table->table_data_ptr[0]);
tfree(rwsptr->reduction_fsa->table->table_data_ptr);
fsa_table_init(rwsptr->reduction_fsa->table, rwsptr->current_maxstates,
rwsptr->num_gens);
tfree(rwsptr->preflen);
tfree(rwsptr->prefno);
tmalloc(rwsptr->preflen, int, rwsptr->current_maxstates + 1);
tmalloc(rwsptr->prefno, int, rwsptr->current_maxstates + 1);
rwsptr->double_states = FALSE;
}
table = rwsptr->reduction_fsa->table->table_data_ptr; if (rwsptr->rk_on)
rk_reset(rwsptr->maxeqns);
rwsptr->num_states = 1;
rwsptr->maxpreflen = 0;
rwsptr->preflen[1] = rwsptr->prefno[1] = 0; for (i = 1; i <= rwsptr->num_gens; i++)
set_dense_target(table, i, 1, 0); for (i = 1; i <= rwsptr->num_eqns; i++) { if (modify_table(i, rwsptr) == -1) {
rwsptr->double_states = TRUE; goto restart;
}
}
}
/* This version returns a table which only rejects the left hand sides *oftherwsptr->eqnsthemselves. *Returnvalueis-1ifrwsptr->current_maxstatesisexceeded-otherwise1.
*/ int modify_table(int relno, rewriting_system *rwsptr)
{ int genno, nextgenno, state, x, l, len, i;
gen *ptr; int **table = rwsptr->reduction_fsa->table->table_data_ptr;
ptr = rwsptr->eqns[relno].lhs;
len = genstrlen(ptr); if (rwsptr->rk_on && len >= rwsptr->rkminlen) {
rk_add_lhs(relno, rwsptr); return1;
} if (len + rwsptr->num_states > rwsptr->current_maxstates) { /* The number of states of the table could exceed the maximum, so we give up *immediately-ifmaxstatesissetwestopcompletely,andotherwisewe *doublerwsptr->current_maxstatesafternexttidying.
*/ if (rwsptr->current_maxstates == rwsptr->maxstates) { if (kbm_print_level > 0)
printf("#Maximum number of states exceeded.\n");
rwsptr->halting = TRUE;
rwsptr->exit_status = 2;
} else { if (kbm_print_level > 2 && kbm_print_level % 3 == 0)
printf( " #Current_maxstates exceeded - will tidy and increase to %d.\n",
rwsptr->current_maxstates * 2);
rwsptr->double_states = TRUE;
}
rwsptr->tidyon = rwsptr->tidyon_now = TRUE; return -1;
}
state = 1;
genno = *(ptr++);
l = 0; while ((nextgenno = *(ptr++))) {
l++;
x = dense_target(table, genno, state); if (x < 0) return1; /* If that happens, the equation must have a prefix which is also a lhs. *Wekeeptheequationfornow-itwillbereducedonthenexttidying.
*/ if (x == 0) {
rwsptr->num_states++; for (i = 1; i <= rwsptr->num_gens; i++)
set_dense_target(table, i, rwsptr->num_states, 0);
rwsptr->preflen[rwsptr->num_states] = l; if (l > rwsptr->maxpreflen)
rwsptr->maxpreflen = l;
rwsptr->prefno[rwsptr->num_states] = relno;
x = rwsptr->num_states;
set_dense_target(table, genno, state, rwsptr->num_states);
}
state = x;
genno = nextgenno;
}
set_dense_target(table, genno, state, -relno); return1;
}
/* Extends the table to one rejecting all strings containing a lhs, *buildsedgesinE_2-E_3asinSims'book,p.118-9.
*/ staticvoid build_fulltable(rewriting_system *rwsptr)
{ int i, j, k, l;
gen *w, *we; int **table = rwsptr->reduction_fsa->table->table_data_ptr; int *preflen = rwsptr->preflen; int *prefno = rwsptr->prefno;
for (i = 1; i <= rwsptr->num_gens; i++) if (dense_target(table, i, 1) == 0)
set_dense_target(table, i, 1, 1); for (l = 1; l <= rwsptr->maxpreflen; l++) { for (j = 2; j <= rwsptr->num_states; j++) if (preflen[j] == l) {
w = rwsptr->eqns[prefno[j]].lhs;
we = w + l;
k = 1; while (++w < we)
k = dense_target(table, *w, k); /* k is the image of 1 under the prefix representing state j,
* but with its first letter removed. */ for (i = 1; i <= rwsptr->num_gens; i++) if (dense_target(table, i, j) == 0)
set_dense_target(table, i, j, dense_target(table, i, k));
}
}
}
/* Compare words w1 and w2 to see which is bigger according to the ordering. *Theorderingusedhereislongerwordsarebigger,andamongstequal *lengthwords,lexicographicalorderingaccordingtotheorderofthe *generatorsasinputisused.(Iuse'bigger'tomeangreaterinthe *ordering.)Returns0ifw1=w2,1ifw1biggerthanw2,otherwise2.
*/ int lex_compare(gen *w1, gen *w2)
{ int len1, len2, bigger = 0;
gen *we1;
/* Compare words w1 and w2 to see which is bigger according to the ordering. *Theorderingusedhereislongerwordsarebigger,wherelengthiscomputed *byaddinguptheweightsofthegeneratorsinthewords,andamongstequal *lengthwords,lexicographicalorderingaccordingtotheorderofthe *generatorsasinputisused.(Iuse'bigger'tomeangreaterinthe *ordering.)Returns0ifw1=w2,1ifw1biggerthanw2,otherwise2.
*/ int wtlex_compare(gen *w1, gen *w2, rewriting_system *rwsptr)
{ int wtlen1, wtlen2, bigger = 0;
gen *wp1, *wp2;
/* Compare words w1 and w2 to see which is 'bigger' according to the ordering.Theorderingusedhereisrecursivepathordering(basedon thatdescribedinthebook"ConfluentStringRewriting"byMatthiasJantzen, Defn1.2.14,page24). Returns1ifw1isbiggerthanw2,2ifw2isbiggerthanw1, 0ifequal. ---------------------------------------------------------------------- Theorderingisasfollows:
1)u=vOR u=u'a,v=v'bforsomea,belementsofX,u',v'elementsofX* andthen: 2)a=bandu'>=v'OR 3)a>bandu>v'OR 4)b>aandu'>v ---------------------------------------------------------------------- Writtenby:JamieP.Curmi(February1992) Correctedby:dfh(December1993)(mustreturn0ifwordsareequal). Alteredbydfh(4.6.94.)toreverseworddirectioninorder, andtoeliminaterecursion.
*/ int rec_compare(gen *w1, gen *w2)
{ int lastmoved = 0;
gen *p1, *p2;
p1 = w1 + genstrlen(w1) - 1;
p2 = w2 + genstrlen(w2) - 1; while (1) { if (p1 < w1) { if (p2 < w2) return lastmoved; return2;
} if (p2 < w2) return1; if (*p1 == *p2) {
p1--;
p2--;
} elseif (*p1 < *p2) {
p1--;
lastmoved = 1;
} elseif (*p2 < *p1) {
p2--;
lastmoved = 2;
}
}
}
/* Compare words w1 and w2 to see which is 'bigger' according to the ordering.Theorderingusedhereisrecursivepathordering(basedon thatdescribedinthebook"ConfluentStringRewriting"byMatthiasJantzen, Defn1.2.14,page24). Returns1ifw1isbiggerthanw2,2ifw2isbiggerthanw1, 0ifequal. ---------------------------------------------------------------------- Theorderingisasfollows:
/* COMPARE: Compares two words 'w1' and 'w2' to see which is 'bigger' *accordingtotheorderingtobeused. *Ifmoreorderingoptionsaretobeprovided,thenewfunctionshould *begivenadifferentnameandcalledfroma'case'statementinthis *function. *Returns0ifw1=w2,1ifw1isbiggerthanw2,otherwise2.
*/ int compare(gen *w1, gen *w2, rewriting_system *rwsptr)
{ switch (rwsptr->ordering) {
case RECURSIVE: /* Recursive path ordering */ return (rec_compare(w1, w2));
case RT_RECURSIVE: /* Recursive path ordering */ return (rt_rec_compare(w1, w2));
build_fulltable(rwsptr); if (rwsptr->cosets && rwsptr->finitestop && (i = check_finite(rwsptr, 128))) {
printf("#Coset language has size %d.", i);
rwsptr->maxoverlaplen =
rwsptr->maxcosetlen + rwsptr->maxlhsrellen > rwsptr->maxsubgenlen
? rwsptr->maxcosetlen + rwsptr->maxlhsrellen
: rwsptr->maxsubgenlen;
printf(" Setting rwsptr->maxoverlap length to %d.\n",
rwsptr->maxoverlaplen);
}
mol = rwsptr->maxoverlaplen;
reduce_word = rws_reduce;
rwsptr->hadlongoverlap = FALSE;
for (i = 1; i <= rwsptr->num_eqns; i++) {
wa = rwsptr->eqns[i].lhs;
la = genstrlen(rwsptr->eqns[i].lhs);
la2 = genstrlen(rwsptr->eqns[i].rhs);
w = wa;
we = w + la;
pl = 0; if (rwsptr->cosets) { /* not interested in inter-subgroup overlaps */ if (!Ggen(*(we - 1))) continue; while (w < we) { if (*w == rwsptr->separator) {
pl = w - wa + 1; break;
}
w++;
}
w = wa;
}
st = 1; while (++w < we)
st = dense_target(table, *w, st);
beta[0] = st;
r = 0;
bt = FALSE; while (r >= 0 && !bt) { if (mol > 0 && r - pl + la > mol) { /* Any further overlap would exceed the permitted length */
rwsptr->hadlongoverlap = TRUE;
bt = TRUE;
}
betar = beta[r];
bt = (bt || (betar < 0 && genstrlen(rwsptr->eqns[-betar].lhs) <= r) ||
(betar >= 0 && preflen[betar] <= r)); if (betar < 0 && !bt) {
genstrcpy(testword1, rwsptr->eqns[i].rhs);
wx = testword1 + la2;
wb = rwsptr->eqns[-betar].lhs;
lb = genstrlen(wb);
w = wb + lb - r;
we = wb + lb; while (w < we)
*(wx++) = *(w++);
*(wx) = 0;
genstrcpy(testword2, rwsptr->eqns[i].lhs);
wx = testword2 + la - lb + r;
genstrcpy(wx, rwsptr->eqns[-betar].rhs); if (reduce_word(testword1, &rs_rws) == -1) {
rwsptr->exit_status = 1; return -1;
} if (reduce_word(testword2, &rs_rws) == -1) {
rwsptr->exit_status = 1; return -1;
} if (genstrlen(testword1) > rwsptr->maxreducelen / 2 ||
genstrlen(testword2) > rwsptr->maxreducelen / 2)
iv = -1; elseif ((iv = insert(&(rwsptr->eqns[rwsptr->num_eqns + 1].lhs),
&(rwsptr->eqns[rwsptr->num_eqns + 1].rhs),
rwsptr)) > 0) { if (rwsptr->print_eqns) {
printf(" #New equation number %d, from fast conf_check on eqn. " "%d:\n",
rwsptr->num_eqns + 1, i);
*kbm_buffer = '\0';
add_to_buffer(6, "#");
n = add_word_to_buffer(stdout,
rwsptr->eqns[rwsptr->num_eqns + 1].lhs,
rwsptr->gen_name);
sprintf(kbm_buffer + strlen(kbm_buffer), "->"); if (n > 0 || strlen(kbm_buffer) > 40) {
printbuffer(stdout);
add_to_buffer(8, "");
}
add_word_to_buffer(stdout, rwsptr->eqns[rwsptr->num_eqns + 1].rhs,
rwsptr->gen_name);
printbuffer(stdout);
}
rwsptr->eqns[++rwsptr->num_eqns].done = FALSE;
num_neweqns++; if (num_neweqns >= rwsptr->tidyint ||
rwsptr->num_eqns == rwsptr->maxeqns) { if (kbm_print_level >= 2)
printf(" #System is not confluent.\n");
rwsptr->tidyon = TRUE; if (rwsptr->num_eqns == rwsptr->maxeqns) { if (kbm_print_level > 0)
printf("#Maximum number of equations exceeded.\n");
rwsptr->hadmaxeqns = TRUE;
rwsptr->hadct++;
rwsptr->tidyon_now = TRUE; if (!rwsptr->worddiffs || rwsptr->hadct > rwsptr->maxhad) {
rwsptr->halting = TRUE;
rwsptr->exit_status = 2;
}
} if (!rwsptr->halting) {
build_quicktable(rwsptr);
reduce_word = slow_rws_reduce;
} return0;
}
} if (iv == -1) /* We have discarded the equation because it is too long. *Sowemustrememberthatthesystemisnotconfluent.
*/
discarded = TRUE;
bt = TRUE;
} if (!bt) {
beta[r + 1] = dense_target(table, 1, betar);
y[r + 1] = 2;
r++;
} else { while (bt && r > 0) { if (y[r] <= rwsptr->num_gens) {
beta[r] = dense_target(table, y[r], beta[r - 1]);
y[r]++;
bt = FALSE;
} else
r--;
}
}
}
} if (num_neweqns > 0) { if (kbm_print_level >= 2)
printf(" #System is not confluent (finished conf_check).\n");
build_quicktable(rwsptr);
reduce_word = slow_rws_reduce; return0;
}
rwsptr->halting = TRUE; if (discarded) { /* We will mark all equations as not done, since we may want to resume with *higherlimitsonequationlength.
*/ for (i = 1; i <= rwsptr->num_eqns; i++)
rwsptr->eqns[i].done = FALSE;
rwsptr->exit_status = 2; return -1;
}
rwsptr->exit_status = 0; return1;
}
/* The equations are re-ordered into order of increasing LHS. *Onlyequationsuptolengthnareoutput.
*/ void sort_eqns(int n, rewriting_system *rwsptr)
{ int i, l, ct, maxl;
gen **newlhs, **newrhs;
boolean *newdone;
maxl = 0; for (i = 1; i <= rwsptr->num_eqns; i++) if ((l = genstrlen(rwsptr->eqns[i].lhs)) > maxl)
maxl = l; if (n > 0 && maxl > n && kbm_print_level > 0) {
printf("#Warning - not all equations will be output.\n"); if (rwsptr->confluent) {
printf("#The output system will not be confluent.\n");
rwsptr->confluent = FALSE;
}
} if (n == 0 || n > maxl)
n = maxl;
tmalloc(newlhs, gen *, rwsptr->num_eqns + 1)
tmalloc(newrhs, gen *, rwsptr->num_eqns + 1)
tmalloc(newdone, boolean, rwsptr->num_eqns + 1) ct = 0; for (l = 1; l <= n; l++) /* Find equations of which LHS has length i */ for (i = 1; i <= rwsptr->num_eqns; i++) if (genstrlen(rwsptr->eqns[i].lhs) == l) {
newlhs[++ct] = rwsptr->eqns[i].lhs;
newrhs[ct] = rwsptr->eqns[i].rhs;
newdone[ct] = rwsptr->eqns[i].done;
} /* and free the rest */ for (i = 1; i <= rwsptr->num_eqns; i++) if (genstrlen(rwsptr->eqns[i].lhs) > n) {
tfree(rwsptr->eqns[i].lhs);
tfree(rwsptr->eqns[i].rhs);
}
for (i = 1; i <= rwsptr->num_eqns; i++) {
rwsptr->eqns[i].lhs = newlhs[i];
rwsptr->eqns[i].rhs = newrhs[i];
rwsptr->eqns[i].done = newdone[i];
}
tfree(newlhs);
tfree(newrhs);
tfree(newdone);
rwsptr->num_eqns = ct;
build_quicktable(rwsptr);
build_fulltable(rwsptr); if (kbm_print_level > 0)
printf("#Output: %d eqns; table has %d states.\n", rwsptr->num_eqns,
rwsptr->num_states);
}
/* Used only in cosets case. *Theequationsnotalreadydonearere-orderedsothatcoseteqnscome *first,thenthoseinvolvingonlyGgenerators,andfinallythoseinvolving *onlyHgenerators.
*/ int type_sort_eqns(int x, rewriting_system *rwsptr)
{ int i, ct, ret;
gen **newlhs, **newrhs;
boolean *newdone; int ne = rwsptr->num_eqns;
reduction_equation *eqn = rwsptr->eqns;
reduction_equation eqni; int sep = rwsptr->separator;
tmalloc(newlhs, gen *, ne + 1) tmalloc(newrhs, gen *, ne + 1)
tmalloc(newdone, boolean, ne + 1) ct = 0;
ret = 0; /* First find equations already done */ for (i = 1; i <= ne; i++) {
eqni = eqn[i]; if (eqni.done) {
newlhs[++ct] = eqni.lhs;
newrhs[ct] = eqni.rhs;
newdone[ct] = eqni.done;
}
}
ret = ct; /* Now those with lhs starting with '_H' */ for (i = 1; i <= ne; i++) {
eqni = eqn[i]; if (!eqni.done && *(eqni.lhs) == sep) {
newlhs[++ct] = eqni.lhs;
newrhs[ct] = eqni.rhs;
newdone[ct] = eqni.done;
}
} /* Next the G-generator equations */ for (i = 1; i <= ne; i++) {
eqni = eqn[i]; if (!eqni.done && Ggen(*(eqni.lhs))) {
newlhs[++ct] = eqni.lhs;
newrhs[ct] = eqni.rhs;
newdone[ct] = eqni.done;
}
} /* And finally the H-generator equations */ for (i = 1; i <= ne; i++) {
eqni = eqn[i]; if (!eqni.done && Hgen(*(eqni.lhs))) {
newlhs[++ct] = eqni.lhs;
newrhs[ct] = eqni.rhs;
newdone[ct] = eqni.done;
}
}
for (i = 1; i <= ne; i++) {
eqn[i].lhs = newlhs[i];
eqn[i].rhs = newrhs[i];
eqn[i].done = newdone[i];
}
tfree(newlhs);
tfree(newrhs);
tfree(newdone);
build_quicktable(rwsptr); return ret;
}
/* Used only in cosets case. *Asfortype_sort_eqns,butdoneattheend,sowedonotworryabout *whatisalreadydone. *Thisistosortoutthedifferentcategoriesofequationsfor *thecosetsenumeration.
*/ void type_sort_eqns_final(rewriting_system *rwsptr)
{ int i, ct;
gen **newlhs, **newrhs;
boolean *newdone; int ne = rwsptr->num_eqns;
reduction_equation *eqn = rwsptr->eqns;
reduction_equation eqni; int sep = rwsptr->separator;
tmalloc(newlhs, gen *, ne + 1) tmalloc(newrhs, gen *, ne + 1)
tmalloc(newdone, boolean, ne + 1) ct = 0; /* First find equations with lhs starting with '_H' */ for (i = 1; i <= ne; i++) {
eqni = eqn[i]; if (*(eqni.lhs) == sep) {
newlhs[++ct] = eqni.lhs;
newrhs[ct] = eqni.rhs;
newdone[ct] = eqni.done;
}
}
/* Now the G-generator equations */ for (i = 1; i <= ne; i++) {
eqni = eqn[i]; if (Ggen(*(eqni.lhs))) {
newlhs[++ct] = eqni.lhs;
newrhs[ct] = eqni.rhs;
newdone[ct] = eqni.done;
}
} /* And finally the H-generator equations */ for (i = 1; i <= ne; i++) {
eqni = eqn[i]; if (Hgen(*(eqni.lhs))) {
newlhs[++ct] = eqni.lhs;
newrhs[ct] = eqni.rhs;
newdone[ct] = eqni.done;
}
}
for (i = 1; i <= ne; i++) {
eqn[i].lhs = newlhs[i];
eqn[i].rhs = newrhs[i];
eqn[i].done = newdone[i];
}
tfree(newlhs);
tfree(newrhs);
tfree(newdone);
rwsptr->num_eqns = ct;
build_quicktable(rwsptr);
build_fulltable(rwsptr); if (kbm_print_level > 0)
printf("#Output: %d eqns; table has %d states.\n", rwsptr->num_eqns,
rwsptr->num_states);
}
/* Used only in cosets case. *Thisiscalledinplaceoftype_sort_eqns_final,whenwewishtooutput *inorderofincreasinglength.Westilloutputintheorderofthe *threecategoriesofequations,butorderbylengthofLHSwithinthem. *Onlyequationsuptolengthn(excludingseparator)areoutput.
*/ void typelength_sort_eqns(int n, rewriting_system *rwsptr)
{ int i, l, ct, maxl;
gen *lhs, **newlhs, **newrhs;
boolean *newdone; int ne = rwsptr->num_eqns;
reduction_equation *eqn = rwsptr->eqns;
reduction_equation eqni = {0,0,0,0,0}; int sep = rwsptr->separator;
maxl = 0; for (i = 1; i <= ne; i++) {
lhs = eqn[i].lhs;
l = *lhs == sep ? genstrlen(lhs + 1) : genstrlen(lhs); if (l > maxl)
maxl = l;
} if (n > 0 && maxl > n && kbm_print_level > 0) {
printf("#Warning - not all equations will be output.\n"); if (rwsptr->confluent) {
printf("#The output system will not be confluent.\n");
rwsptr->confluent = FALSE;
}
} if (n == 0 || n > maxl)
n = maxl;
tmalloc(newlhs, gen *, ne + 1) tmalloc(newrhs, gen *, ne + 1)
tmalloc(newdone, boolean, ne + 1) ct = 0; /* First the coset equations */ for (l = 1; l <= n; l++) /* Find equations of which LHS has length i */ for (i = 1; i <= ne; i++) {
eqni = eqn[i];
lhs = eqni.lhs; if (*lhs == sep && genstrlen(lhs + 1) == l) {
newlhs[++ct] = lhs;
newrhs[ct] = eqni.rhs;
newdone[ct] = eqni.done;
}
} /* Now the G-generator equations */ for (l = 1; l <= n; l++) /* Find equations of which LHS has length i */ for (i = 1; i <= ne; i++) {
eqni = eqn[i];
lhs = eqni.lhs; if (Ggen(*lhs) && genstrlen(lhs) == l) {
newlhs[++ct] = eqni.lhs;
newrhs[ct] = eqni.rhs;
newdone[ct] = eqni.done;
}
} /* And finally the H-generator equations */ for (l = 1; l <= n; l++) /* Find equations of which LHS has length i */ for (i = 1; i <= ne; i++) {
lhs = eqni.lhs; if (Hgen(*lhs) && genstrlen(lhs) == l) {
newlhs[++ct] = lhs;
newlhs[++ct] = eqni.lhs;
newrhs[ct] = eqni.rhs;
newdone[ct] = eqni.done;
}
}
/* Free the rest (those that are too long) */ for (i = 1; i <= ne; i++) {
lhs = eqni.lhs;
l = *lhs == sep ? genstrlen(lhs + 1) : genstrlen(lhs); if (l > n) {
tfree(rwsptr->eqns[i].lhs);
tfree(rwsptr->eqns[i].rhs);
}
}
for (i = 1; i <= rwsptr->num_eqns; i++) {
eqn[i].lhs = newlhs[i];
eqn[i].rhs = newrhs[i];
eqn[i].done = newdone[i];
}
tfree(newlhs);
tfree(newrhs);
tfree(newdone);
rwsptr->num_eqns = ct;
build_quicktable(rwsptr);
build_fulltable(rwsptr); if (kbm_print_level > 0)
printf("#Output: %d eqns; table has %d states.\n", rwsptr->num_eqns,
rwsptr->num_states);
}
/* The equations are re-ordered so that those that resulted in new entries *intheword-differencetablecomefirst. *Thosearerecordedinthebooleanarraynew_wd. *xisthecurrentequationnumberintheKB.
*/ int wd_sort_eqns(int x, rewriting_system *rwsptr)
{ int i, j, ct, ret, newmaxeqns = 0; int ne = rwsptr->num_eqns;
reduction_equation *eqn = rwsptr->eqns;
reduction_equation eqni; int sep = rwsptr->separator;
boolean *nwd = rwsptr->new_wd;
gen **newlhs, **newrhs;
boolean *newdone; double r;
if (rwsptr->hadmaxeqns) { /* In this case we will not keep all equations, to allow room for more */
r = (double)x / rwsptr->num_eqns; if (r > 0.75) { if (kbm_print_level >= 2)
printf(" #Halting - r=%f, rwsptr->hadct=%d.\n", r, rwsptr->hadct);
rwsptr->halting = TRUE;
rwsptr->exit_status = 2;
rwsptr->hadmaxeqns = FALSE;
} else
newmaxeqns = ne * (1 + r) / 2;
}
tmalloc(newlhs, gen *, ne + 1) tmalloc(newrhs, gen *, ne + 1)
tmalloc(newdone, boolean, ne + 1) ct = 0; /* Find equations that are already done */ for (i = 1; i <= ne; i++) {
eqni = eqn[i]; if (eqni.done) {
newlhs[++ct] = eqni.lhs;
newrhs[ct] = eqni.rhs;
newdone[ct] = eqni.done;
}
}
ret = ct; /* Next those that gave new word-diffs */ for (i = 1; i <= ne; i++) {
eqni = eqn[i]; if (!eqni.done && nwd[i]) {
newlhs[++ct] = eqni.lhs;
newrhs[ct] = eqni.rhs;
newdone[ct] = eqni.done;
}
} /* Now take the rest. */ if (rwsptr->cosets) { for (i = 1; i <= ne; i++) {
eqni = eqn[i]; if (*(eqni.lhs) == sep && !eqni.done && !nwd[i]) {
newlhs[++ct] = eqni.lhs;
newrhs[ct] = eqni.rhs;
newdone[ct] = eqni.done;
}
} for (i = 1; i <= ne; i++) {
eqni = eqn[i]; if (Ggen(*(eqni.lhs)) && !eqni.done && !nwd[i]) {
newlhs[++ct] = eqni.lhs;
newrhs[ct] = eqni.rhs;
newdone[ct] = eqni.done;
}
} for (i = 1; i <= ne; i++) {
eqni = eqn[i]; if (Hgen(*(eqni.lhs)) && !eqni.done && !nwd[i]) {
newlhs[++ct] = eqni.lhs;
newrhs[ct] = eqni.rhs;
newdone[ct] = eqni.done;
}
}
} else for (i = 1; i <= ne; i++) {
eqni = eqn[i]; if (!eqni.done && !rwsptr->new_wd[i]) {
newlhs[++ct] = eqni.lhs;
newrhs[ct] = eqni.rhs;
newdone[ct] = eqni.done; if (rwsptr->hadmaxeqns && ct >= newmaxeqns) { if (kbm_print_level > 0)
printf("Keeping only %d equations.\n", ct); /* free the rest */ for (j = i + 1; j <= ne; j++) if (!eqn[j].done && !nwd[j]) {
tfree(rwsptr->eqns[j].lhs);
tfree(rwsptr->eqns[j].rhs);
}
rwsptr->num_eqns = ct;
rwsptr->hadmaxeqns = FALSE; break;
}
}
} for (i = 1; i <= ne; i++) {
eqn[i].lhs = newlhs[i];
eqn[i].rhs = newrhs[i];
eqn[i].done = newdone[i];
}
tfree(newlhs);
tfree(newrhs);
tfree(newdone);
build_quicktable(rwsptr); return ret;
}
/* Try to decide whether we should halt, using number of word-differences. */ void should_we_halt(rewriting_system *rwsptr)
{ int i, ndiff, t; struct rusage tmp;
getrusage(RUSAGE_SELF, &tmp);
t = tmp.ru_utime.tv_sec;
rwsptr->num_cycles++; if (rwsptr->num_cycles >= MAXCYCLES) {
rwsptr->halting = TRUE;
rwsptr->exit_status = 2;
}
rwsptr->wd_record[rwsptr->num_cycles].num_eqns = rwsptr->tot_eqns;
rwsptr->wd_record[rwsptr->num_cycles].num_states = rwsptr->num_states;
ndiff = rwsptr->wd_record[rwsptr->num_cycles].num_diff =
rwsptr->wd_fsa->states->size; for (i = rwsptr->num_cycles - 1; i >= 1; i--) if (rwsptr->wd_record[i].num_diff < ndiff) break;
i++;
rwsptr->eqn_factor =
rwsptr->wd_record[i].num_eqns == 0
? 0
: 100 * rwsptr->tot_eqns / rwsptr->wd_record[i].num_eqns - 100;
rwsptr->states_factor =
rwsptr->hadct > 0
? 0
: 100 * rwsptr->num_states / rwsptr->wd_record[i].num_states - 100; if (rwsptr->halting_factor > 0 &&
((t > rwsptr->min_time && rwsptr->eqn_factor >= rwsptr->halting_factor &&
(rwsptr->states_factor == 0 ||
rwsptr->states_factor >= rwsptr->halting_factor)) ||
(rwsptr->eqn_factor >= 2 * rwsptr->halting_factor &&
rwsptr->states_factor >= 2 * rwsptr->halting_factor))) { if (kbm_print_level > 1)
printf(" #eqn_factor=%d, states_factor=%d - halting.\n",
rwsptr->eqn_factor, rwsptr->states_factor);
rwsptr->halting = TRUE;
rwsptr->exit_status = 0;
}
}
/* Used only in cosets case. *Wefinishbyadjustingthereductionfsatoensurethatitonlyaccepts *wordsinG-Generatorsalone,wordsinH-generatorsalone,orwordsof *formH-word*separator*G-word.
*/ void make_fsa_nice(rewriting_system *rwsptr)
{ int first_Hstate, i, j, ng, im; int **table = rwsptr->reduction_fsa->table->table_data_ptr;
if (dense_target(table, rwsptr->separator, 1) != 2) {
fprintf(stderr, "Error: Why is image of 1 under separator not 2?\n"); return;
}
ng = rwsptr->num_gens;
first_Hstate = rwsptr->num_states + 1; for (i = rwsptr->separator + 1; i <= ng; i++) {
im = dense_target(table, i, 1); if (im > 0 && im < first_Hstate)
first_Hstate = im;
} /* A G-generator cannot directly follow an H-generator */ for (i = 1; i < rwsptr->separator; i++) for (j = first_Hstate; j <= rwsptr->num_states; j++)
set_dense_target(table, i, j, 0); /* And _H or an H-generator cannot follow _H or a G-generator */ for (i = rwsptr->separator; i <= ng; i++) for (j = 2; j < first_Hstate; j++)
set_dense_target(table, i, j, 0);
}
/* This is based on fsa_enumerate. It checks whether *thecosetlanguageacceptedmightbefinite-byenumeratingitup *tolengthmax.Iftheenumerationcompletesandnowordhaslengthequalto *max,thenitmustbe. *Iffinite,thesizeofthelanguageisreturned-otherwise0.
*/ int check_finite(rewriting_system *rwsptr, int max)
{ int i, ne, **table, ct, *cword, firste, clength, cstate, im, *statelist;
boolean done, backtrack;
fsa *fsaptr = rwsptr->reduction_fsa;
if (fsaptr->num_initial == 0) returnFALSE;
ne = fsaptr->alphabet->size;
table = fsaptr->table->table_data_ptr;
tmalloc(cword, int,
max + 1); /* to hold the current word in the enumeration */
*kbm_buffer = '\0';
tmalloc(statelist, int, max + 1); /* this is used to store the state history on scanning the current word. */ for (i = 0; i <= max; i++)
cword[i] = 0;
clength = 0;
statelist[0] = dense_target(table, rwsptr->separator, fsaptr->initial[1]);
/* Backtrack search can now begin */
done = FALSE;
ct = 0;
rwsptr->maxcosetlen = 0; while (!done) {
ct++; /* Now proceed to next word in the search */
firste = 1;
backtrack = TRUE; while (backtrack && !done) { if (clength < max) {
cstate = statelist[clength];
i = firste - 1; while (backtrack && ++i <= ne) if (Ggen(i) && (im = dense_target(table, i, cstate)) > 0) { /* found next node */
cword[clength++] = i;
statelist[clength] = im;
backtrack = FALSE; if (clength == max) return0; if (clength > rwsptr->maxcosetlen)
rwsptr->maxcosetlen = clength;
}
} if (backtrack) { if (clength == 0)
done = TRUE; else {
firste = cword[--clength] + 1;
cword[clength] = '\0';
}
}
}
}
tfree(cword);
tfree(statelist);
return ct;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.48 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.