magic/src/logic_io.c

835 lines
16 KiB
C

/*
* logic_io.c V2.1 (May 1993)
*
* This file contains the routines for reading in setups
* and for making the appropriate initialisations. It
* also contains the procedures for printing any matrices
* found.
*/
/****************************************************************
* *
* MaGIC 2.1 *
* *
* (C) 1992 Australian National University *
* *
* All rights reserved *
* *
* The information in this software is subject to change without *
* notice and should not be construed as a commitment by the *
* Australian National University. The Australian National Uni- *
* versity makes no representations about the suitability of *
* this software for any purpose. It is supplied "as is" without *
* express or implied warranty. If the software is modified in *
* a manner creating derivative copyright rights, appropriate *
* legends may be placed on the derivative work in addition to *
* that set forth above. *
* *
* Permission to use, copy, modify and distribute this software *
* and its documentation for any purpose and without fee is *
* hereby granted, provided that both the above copyright notice *
* and this permission notice appear in all copies and sup- *
* porting documentation, and that the name of the Australian *
* National University not be used in advertising or publicity *
* pertaining to distribution of the software without specific, *
* written prior permission. *
* *
****************************************************************/
#include "MaGIC.h"
/*
* First the semi-trivial function cluster to control the loop
*/
int newsiz()
{
N[0] = 0;
return( got_siz()? (theJob->f_n? newneg(): neword()): 0 );
}
int newneg()
{
return( got_neg()? neword(): newsiz() );
}
int neword()
{
return( got_ord()? newdes(): (theJob->f_n? newneg(): newsiz()) );
}
int newdes()
{
return( got_des()? 1: neword() );
}
/*
* Sep is a subroutine to print the separator "-1" if the
* chosen format is UGLY. The parameter is the counter for
* the appropriate level.
*/
void sep(int *x)
{
if ( *x ) {
if ( theJob->tty_out==UGLY ) printf(" -1\n");
if ( theJob->fil_out==UGLY ) fprintf(outfil, " -1\n");
*x = 0;
}
}
/*
* Next_bit returns 1 or 0 depending on the next bit in the
* input file. This is to allow very compressed data to be used.
*/
int next_bit()
{
if ( input_bit == 8 ) {
if ( read(infil,&buffa,1) < 1 ) return 0;
input_bit = 0;
}
if ( buffa & ((char)1 << input_bit++) ) return 1;
return 0;
}
/*
* Return the new size, or 0 if there isn't one.
* The values of T and F are incidentally set at this stage.
*/
int got_siz()
{
if ( theJob->f_n )
sep( &negno );
else sep( &ordno );
if ( next_bit() ) siz++; else siz = 0;
if ( tr_par.done || siz>=theJob->sizmax ) siz = 0;
if ( theJob->f_T ) theJob->form[VMAX+2].val = siz;
if ( theJob->f_F ) theJob->form[VMAX+3].val = 0;
return siz;
}
/*
* Set the next negation table.
* Return 1 if successful, 0 if not.
*/
boolean got_neg()
{
int i;
sep(&ordno);
if ( tr_par.done || !next_bit() ) return false;
if ( N[0] ) {
FORaLL(i)
if ( N[i] > i ) break;
N[N[i]] = N[i];
N[i] = i;
}
else FORALL(i) N[i] = siz-i;
return true;
}
/*
* Read the next order table.
* Return 1 if successful, 0 if not.
* At this stage, decide which elements are maximal, define
* lattice meet and join if they exist, and set up cc, the
* index to the communication vector of transref.
*/
boolean got_ord()
{
int i, j, k;
sep( &desno );
if ( tr_par.done || !next_bit() ) return false;
FORALL(i) FORALL(j)
if ( i < j ) ord[i][j] = next_bit();
else ord[i][j] = (i == j);
FORALL(i) {
maximal[i] = 1;
for ( j = i+1; j <=siz; j++ ) maximal[i] *= !ord[i][j];
}
if ( theJob->f_lat ) {
FORALL(i) {
for ( j = i; j <= siz; j++ ) {
for (k = j; !(ord[i][k] && ord[j][k]); k++) ;
A[i][j] = A[j][i] = k;
for (k = i; !(ord[k][i] && ord[k][j]); k--) ;
K[i][j] = K[j][i] = k;
}
}
}
set_up_cc();
return true;
}
/*
* Read the next choice of designated values, or of least
* designated value if t is defined.
* Return 1 on success, 0 on failure.
*
* The set of designated (true) values can be calculated
* here, and the values of t and f filled in.
*/
boolean got_des()
{
int i;
if ( matsum ) {
if ( theJob->tty_out == SUMMARY ) {
printf(" %d matri%s",
matsum, (matsum>1? "ces": "x"));
fflush(stdout);
}
if ( theJob->fil_out == SUMMARY )
fprintf(outfil, " %d matri%s",
matsum, (matsum>1? "ces": "x"));
matsum = 0;
}
sep( &matno );
if ( tr_par.done || !next_bit() ) return false;
FORALL(i) desig[i] = next_bit();
for ( des = 0; !desig[des]; des++ ) ;
for ( undes = siz; desig[undes]; undes-- ) ;
if ( theJob->f_t ) {
theJob->form[VMAX].val = des;
if ( theJob->f_n ) theJob->form[VMAX+1].val = N[des];
}
return true;
}
/*
======================================================================
*/
/*
* That's the end of the input routines. Now for the output ones.
*
* Mat_print is called from the tester with each good matrix.
*/
void mat_print()
{
int i, j;
boolean b;
firstchange = -1;
for ( i = 0; i < tr_par.vlength; i++ ) {
if ( thisvector[i] != thatvector[i] ) firstchange = i;
thatvector[i] = thisvector[i];
}
if ( !matno ) firstchange = tr_par.vlength;
if ( firstchange < 0 ) skipout("Same matrix found twice",SKIP);
j = -1;
for ( i = 0; theJob->dcs[i]; i++ );
for (--i; i >= 0; i--)
if ( theJob->defcon[i] == PRIMITIVE ) {
switch( theJob->adicity[i] ) {
case 0:
newmatplus( j, ucc0[i] );
break;
case 1:
newmatplus( j, ucc1[i][0] );
break;
case 2:
newmatplus( j, ucc2[i][0][0] );
}
j = i;
}
if ( theJob->f_nec ) {
newmatplus( j, firstbox );
if ( firstchange >= firstarrow ) sep(&boxno);
}
else newmatplus( j, firstarrow );
b = true;
for ( i = 0; theJob->dcs[i]; i++ );
for ( --i; i>=0; i-- )
if ( theJob->defcon[i] == PRIMITIVE )
if ( matplus[i]++ ) {
b = false;
break;
}
if ( b && theJob->f_nec )
if ( boxno++ ) b = false;
if ( b )
if ( !matno++ )
if ( !desno++ )
if ( !ordno++ )
if ( theJob->f_n )
negno++;
good++;
matsum++;
if ( theJob->tty_out ) printup(stdout,theJob->tty_out);
if ( theJob->fil_out ) printup(outfil,theJob->fil_out);
}
/*
* Essentially a macro for the above:
*/
void newmatplus(int x, int y)
{
if ( firstchange >= y && x >= 0 ) sep(matplus+x);
}
/*
* Printing the new size is part of printing the new negation
* table or, if negation is not defined, the new order table.
* The parameter x is the output mode, and f the destination.
*/
void siz_print(FILE *f, output_style x)
{
switch(x) {
case UGLY:
fprintf(f, " %d\n", siz);
break;
case PRETTY:
fprintf(f, "\n\n\n\n Size: %d\n", siz+1);
break;
case SUMMARY:
fprintf(f, "\n\n\n Size: %d", siz+1);
case NONE:
break;
}
}
/*
* Printing the new negation table is part of printing the new
* order table.
* The parameter x is the output mode, and f the destination.
*/
void neg_print(FILE *f, output_style x)
{
int i;
if ( negno == 1 ) siz_print(f,x);
switch(x) {
case UGLY:
FORALL(i) fprintf(f, " %d", N[i]);
fprintf(f, "\n");
break;
case PRETTY:
fprintf(f, "\n\n Negation table ");
pretty_negno(f);
fprintf(f, "\n\n a |");
FORALL(i) fprintf(f, " %x", i);
fprintf(f, "\n ---+");
FORALL(i) fprintf(f, "--");
fprintf(f, "\n ~a |");
FORALL(i) fprintf(f, " %x", N[i]);
fprintf(f, "\n");
break;
case SUMMARY:
fprintf(f, "\n\n Negation ");
pretty_negno(f);
case NONE:
break;
}
}
/*
* Printing the new order table is part of printing the new
* choice of designated values.
* The parameter x is the output mode, and f the destination.
*/
void ord_print(FILE *f, output_style x)
{
int i, j;
if ( ordno == 1 ) {
if ( theJob->f_n ) neg_print(f,x);
else siz_print(f,x);
}
switch(x) {
case NONE:
break;
case UGLY:
FORALL(i) FORALL(j)
fprintf(f, " %d", ord[i][j]);
fprintf(f, "\n");
break;
case PRETTY:
fprintf(f, "\n\n Order ");
pretty_ordno(f);
fprintf(f, "\n\n < |");
FORALL(i) fprintf(f, " %x", i);
fprintf(f, "\n --+");
FORALL(i) fprintf(f, "--");
FORALL(i)
{ fprintf(f, "\n%10x |", i);
FORALL(j)
fprintf(f, " %c", (ord[i][j]? '+': '-'));
}
fprintf(f, "\n");
break;
case SUMMARY:
fprintf(f, "\n\n Order ");
pretty_ordno(f);
}
}
/*
* Printing the new choice of designated values is part of
* printing the new implication matrix.
* The parameter x is the output mode, and f the destination.
*
* If t is defined only it is printed. Otherwise the true
* values are listed. In ugly format, the boolean vector
* true (1 if value is designated, 0 if not) is printed.
* Note that this convention for ugly output is different
* from that of MaGIC version 1.1 and causes incompatibility
* with post-processing software.
*/
void des_print(FILE *f, output_style x)
{
int i;
if ( desno == 1 ) ord_print(f,x);
switch(x) {
case NONE:
break;
case UGLY:
FORALL(i) fprintf(f, " %d", desig[i]);
fprintf(f, "\n" );
break;
case PRETTY:
if ( theJob->f_t ) {
fprintf(f, "\n\n Choice ");
pretty_desno(f);
fprintf(f, " of t: %x\n", des);
}
else {
fprintf(f, "\n\n Choice ");
pretty_desno(f);
fprintf(f, " of truths: ");
FORALL(des) if ( desig[des] )
fprintf(f, " %x", des);
fprintf(f, "\n");
}
break;
case SUMMARY:
if ( theJob->f_t )
fprintf(f, "\n\n t = %x", des);
else {
fprintf(f, "\n\n truth =");
FORALL(des) if ( desig[des] )
fprintf(f, " %x", des);
}
}
}
/*
* Printing the new implication matrix is part of printing
* the new algebra.
* The parameter x is the output mode, and f the destination.
*/
void C_print(FILE *f, output_style x)
{
int i, j;
if ( matno == 1 ) des_print(f,x);
switch(x) {
case SUMMARY:
case NONE:
return;
case UGLY:
FORALL(i) FORALL(j) fprintf(f, " %d", C[i][j]);
break;
case PRETTY:
fprintf(f, "\n\n Implication matrix ");
pretty_matno(f);
fprintf(f, "\n\n -> |");
FORALL(i) fprintf(f, " %x", i);
fprintf(f, "\n ---+");
FORALL(i) fprintf(f, "--");
FORALL(i) {
fprintf(f, "\n%10x |", i);
FORALL(j) fprintf(f, " %x", C[i][j]);
}
fprintf(f, "\n");
}
}
/*
* Printing a new ! table may be part of printup.
* The parameter x is the output mode, and f the destination.
*/
void box_print(FILE *f, output_style x)
{
int i;
switch(x) {
case UGLY:
FORALL(i) fprintf(f, " %d", box[i]);
fprintf(f, "\n");
break;
case PRETTY:
fprintf(f, "\n ! matrix ");
pretty_boxno( f );
fprintf(f, "\n\n a |");
FORALL(i) fprintf(f, " %x", i);
fprintf(f, "\n ---+");
FORALL(i) fprintf(f, "--");
fprintf(f, "\n !a |");
FORALL(i) fprintf(f, " %x", box[i]);
if ( theJob->f_n ) {
fprintf(f, "\n ?a |");
FORALL(i) fprintf(f, " %x", diamond[i]);
}
fprintf(f, "\n");
break;
case SUMMARY:
case NONE:
return;
}
}
/*
* Printing a nulladic user connective may be part of printup.
* The parameter x is the output mode, and f the destination.
*/
void u_print0(FILE *f, output_style x, int y)
{
switch(x) {
case UGLY:
fprintf(f, " %d\n", nulladic[y]);
break;
case PRETTY:
fprintf(f, "\n Choice ");
pretty_umat( f, y );
fprintf(f, " of %s: %x\n",
theJob->dcs[y]->s, nulladic[y]);
break;
case SUMMARY:
case NONE:
return;
}
}
/*
* Printing a monadic user connective may be part of printup.
* The parameter x is the output mode, and f the destination.
*/
void u_print1(FILE *f, output_style x, int y)
{
int i;
switch(x) {
case UGLY:
FORALL(i) fprintf(f, " %d", monadic[y][i]);
fprintf(f, "\n");
break;
case PRETTY:
fprintf(f, "\n %s matrix ", theJob->dcs[y]->s);
pretty_umat( f, y );
fprintf(f, "\n\n ");
for ( i = 0; i < strlen(theJob->dcs[y]->s); i++ )
printf(" ");
fprintf(f, "a |");
FORALL(i) fprintf(f, " %x", i);
fprintf(f, "\n ----");
for ( i = 0; i < strlen(theJob->dcs[y]->s); i++ )
printf("-");
fprintf(f, "+");
FORALL(i) fprintf(f, "--");
fprintf(f, "\n %s(a) |", theJob->dcs[y]->s);
FORALL(i) fprintf(f, " %x", monadic[y][i]);
fprintf(f, "\n");
break;
case SUMMARY:
case NONE:
return;
}
}
/*
* Printing a dyadic user connective may be part of printup.
* The parameter x is the output mode, and f the destination.
*/
void u_print2(FILE *f, output_style x, int y)
{
int i, j, k;
switch(x) {
case NONE:
case SUMMARY:
return;
case UGLY:
FORALL(i) FORALL(j)
fprintf(f, " %d", dyadic[y][i][j]);
break;
case PRETTY:
fprintf(f, "\n %s matrix ", theJob->dcs[y]->s);
pretty_umat( f, y );
fprintf(f, "\n\n %s |",
theJob->dcs[y]->s);
FORALL(i) fprintf(f, " %x", i);
fprintf(f, "\n --");
for ( i = 0; i < strlen(theJob->dcs[y]->s); i++ )
printf("-");
fprintf(f, "+");
FORALL(i) fprintf(f, "--");
FORALL(i) {
fprintf(f, "\n");
for ( k = 0; k < strlen(theJob->dcs[y]->s); k++ )
printf(" ");
fprintf(f, "%19x |", i);
FORALL(j)
fprintf(f, " %x", dyadic[y][i][j]);
}
fprintf(f, "\n");
}
}
/*
* This is the printup routine called with every good matrix.
* The parameter x is the output mode, and f the destination.
*/
void printup(FILE *f, output_style x)
{
int i;
if ( firstchange >= firstarrow ) C_print(f,x);
if ( theJob->f_nec && firstchange >= firstbox ) box_print(f,x);
for ( i = 0; theJob->dcs[i]; i++ )
if ( theJob->defcon[i] == PRIMITIVE )
switch( theJob->adicity[i] ) {
case 0:
if ( firstchange >= ucc0[i] )
u_print0(f,x,i);
break;
case 1:
if (firstchange >= ucc1[i][0] )
u_print1(f,x,i);
break;
case 2:
if (firstchange >= ucc2[i][0][0] )
u_print2(f,x,i);
}
if ( x == PRETTY ) {
if ( theJob->failure ) fail_print(f);
fprintf(f, "\n");
fflush(f);
}
}
/*
* This is the series of functions for pretty-printing the
* matrix numbers.
*/
void pretty_size(FILE *f)
{
fprintf( f, "%d", siz+1 );
}
void pretty_negno(FILE *f)
{
pretty_size(f);
fprintf( f, ".%d", negno );
}
void pretty_ordno(FILE *f)
{
if ( theJob->f_n )
pretty_negno(f);
else pretty_size(f);
fprintf( f, ".%d", ordno );
}
void pretty_desno(FILE *f)
{
pretty_ordno(f);
fprintf( f, ".%d", desno );
}
void pretty_matno(FILE *f)
{
pretty_desno(f);
fprintf( f, ".%d", matno );
}
void pretty_boxno(FILE *f)
{
pretty_matno(f);
if ( theJob->f_nec ) fprintf( f, ".%d", boxno );
}
/*
* DOES NOT LOOK RIGHT AT ALL
*
void pretty_umat(FILE *f, int x)
{
int i;
for ( i = x-1; i >= 0; i-- )
if ( theJob->defcon[i] == PRIMITIVE ) {
pretty_umat( f, i );
break;
}
if ( i < 0 ) pretty_matno(f);
fprintf( f, ".%d", matplus[x] );
}
*
*/
void pretty_umat(FILE *f, int x)
{
if ( x < 0 ) pretty_boxno(f);
else {
pretty_umat(f,x-1);
if ( theJob->defcon[x] == PRIMITIVE )
fprintf( f, ".%d", matplus[x] );
}
}
/*
* The assignment of values failing the bad guy is appended to
* each structure recorded in pretty format.
*/
void fail_print(FILE *f)
{
insert_badvalues( theJob->failure );
fprintf(f,"\n Failure: ");
outformula( theJob->failure, theJob->failure, f, VALS );
fprintf(f,"\n");
}
void insert_badvalues( int offset )
{
if ( !offset ) return;
insert_badvalues( theJob->form[offset].lsub );
insert_badvalues( theJob->form[offset].rsub );
if ( offset <= Vmax ) theJob->form[offset].val = badvalue[offset];
}
/*
* At the end of a job some runtime statistics are sent to
* stdout. Note that this is not done in batch mode.
*/
void stats_print()
{
int tim;
CLoCK(&tim);
printf("\n\n\n\n\n Matrices generated by MaGIC: ");
fflush(stdout);
system("date");
printf("\n\n Good ones found: %d\n", good);
printf(" Bad ones tested: %d\n", tot-(good+isoms+isoms2));
printf(" Isomorphs omitted: %d", isoms);
if ( isoms2 ) printf(" + %d", isoms2);
#ifdef HASTIMES
end_timer = time_buffer.tms_utime;
printf("\n Time (cpu): %1.2f seconds",
(end_timer - begin_timer)/(1.0*CLK_TCK));
#endif
printf("\n Time (wall clock): %1.2f seconds\n\n\n",
(tim - start_time)/(TICK*1.0));
}