Esempio n. 1
0
/**Function********************************************************************

  Synopsis    [Main function for testcudd.]

  Description []

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
int
main(int argc, char **argv)
{
    FILE *fp;           /* pointer to input file */
    char *file = (char *) "";	/* input file name */
    FILE *dfp = NULL;	/* pointer to dump file */
    char *dfile;	/* file for DD dump */
    DdNode *dfunc[2];	/* addresses of the functions to be dumped */
    DdManager *dd;	/* pointer to DD manager */
    DdNode *_true;	/* fast access to constant function */
    DdNode *M;
    DdNode **x;		/* pointers to variables */
    DdNode **y;		/* pointers to variables */
    DdNode **xn;       	/* complements of row variables */
    DdNode **yn_;      	/* complements of column variables */
    DdNode **xvars;
    DdNode **yvars;
    DdNode *C;		/* result of converting from ADD to BDD */
    DdNode *ess;	/* cube of essential variables */
    DdNode *shortP;	/* BDD cube of shortest path */
    DdNode *largest;	/* BDD of largest cube */
    DdNode *shortA;	/* ADD cube of shortest path */
    DdNode *constN;	/* value returned by evaluation of ADD */
    DdNode *ycube;	/* cube of the negated y vars for c-proj */
    DdNode *CP;		/* C-Projection of C */
    DdNode *CPr;	/* C-Selection of C */
    int    length;	/* length of the shortest path */
    int    nx;			/* number of variables */
    int    ny;
    int    maxnx;
    int    maxny;
    int    m;
    int    n;
    int    N;
    int    cmu;			/* use CMU multiplication */
    int    pr;			/* verbose printout level */
    int    harwell;
    int    multiple;		/* read multiple matrices */
    int    ok;
    int    c;			/* variable to read in options */
    int    approach;		/* reordering approach */
    int    autodyn;		/* automatic reordering */
    int    groupcheck;		/* option for group sifting */
    int    profile;		/* print heap profile if != 0 */
    int    keepperm;		/* keep track of permutation */
    int    clearcache;		/* clear the cache after each matrix */
    int    blifOrDot;		/* dump format: 0 -> dot, 1 -> blif, ... */
    int    retval;		/* return value */
    int    i;			/* loop index */
    long   startTime;		/* initial time */
    long   lapTime;
    int    size;
    unsigned int cacheSize, maxMemory;
    unsigned int nvars,nslots;

    startTime = util_cpu_time();

    approach = CUDD_REORDER_NONE;
    autodyn = 0;
    pr = 0;
    harwell = 0;
    multiple = 0;
    profile = 0;
    keepperm = 0;
    cmu = 0;
    N = 4;
    nvars = 4;
    cacheSize = 127;
    maxMemory = 0;
    nslots = CUDD_UNIQUE_SLOTS;
    clearcache = 0;
    groupcheck = CUDD_GROUP_CHECK7;
    dfile = NULL;
    blifOrDot = 0; /* dot format */

    /* Parse command line. */
    while ((c = util_getopt(argc, argv, (char *) "CDHMPS:a:bcd:g:hkmn:p:v:x:X:"))
	   != EOF) {
	switch(c) {
	case 'C':
	    cmu = 1;
	    break;
	case 'D':
	    autodyn = 1;
	    break;
	case 'H':
	    harwell = 1;
	    break;
	case 'M':
#ifdef MNEMOSYNE
	    (void) mnem_setrecording(0);
#endif
	    break;
	case 'P':
	    profile = 1;
	    break;
	case 'S':
	    nslots = atoi(util_optarg);
	    break;
	case 'X':
	    maxMemory = atoi(util_optarg);
	    break;
	case 'a':
	    approach = atoi(util_optarg);
	    break;
	case 'b':
	    blifOrDot = 1; /* blif format */
	    break;
	case 'c':
	    clearcache = 1;
	    break;
	case 'd':
	    dfile = util_optarg;
	    break;
	case 'g':
	    groupcheck = atoi(util_optarg);
	    break;
	case 'k':
	    keepperm = 1;
	    break;
	case 'm':
	    multiple = 1;
	    break;
	case 'n':
	    N = atoi(util_optarg);
	    break;
	case 'p':
	    pr = atoi(util_optarg);
	    break;
	case 'v':
	    nvars = atoi(util_optarg);
	    break;
	case 'x':
	    cacheSize = atoi(util_optarg);
	    break;
	case 'h':
	default:
	    usage(argv[0]);
	    break;
	}
    }

    if (argc - util_optind == 0) {
	file = (char *) "-";
    } else if (argc - util_optind == 1) {
	file = argv[util_optind];
    } else {
	usage(argv[0]);
    }
    if ((approach<0) || (approach>17)) {
	(void) fprintf(stderr,"Invalid approach: %d \n",approach);
	usage(argv[0]);
    }

    if (pr >= 0) {
	(void) printf("# %s\n", TESTCUDD_VERSION);
	/* Echo command line and arguments. */
	(void) printf("#");
	for (i = 0; i < argc; i++) {
	    (void) printf(" %s", argv[i]);
	}
	(void) printf("\n");
	(void) fflush(stdout);
    }

    /* Initialize manager and provide easy reference to terminals. */
    dd = Cudd_Init(nvars,0,nslots,cacheSize,maxMemory);
    _true = DD_TRUE(dd);
    dd->groupcheck = (Cudd_AggregationType) groupcheck;
    if (autodyn) Cudd_AutodynEnable(dd,CUDD_REORDER_SAME);

    /* Open input file. */
    fp = open_file(file, "r");

    /* Open dump file if requested */
    if (dfile != NULL) {
	dfp = open_file(dfile, "w");
    }

    x = y = xn = yn_ = NULL;
    do {
	/* We want to start anew for every matrix. */
	maxnx = maxny = 0;
	nx = maxnx; ny = maxny;
	if (pr>0) lapTime = util_cpu_time();
	if (harwell) {
	    if (pr >= 0) (void) printf(":name: ");
	    ok = Cudd_addHarwell(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny,
	    &m, &n, 0, 2, 1, 2, pr);
	} else {
	    ok = Cudd_addRead(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny,
	    &m, &n, 0, 2, 1, 2);
	    if (pr >= 0)
		(void) printf(":name: %s: %d rows %d columns\n", file, m, n);
	}
	if (!ok) {
	    (void) fprintf(stderr, "Error reading matrix\n");
	    exit(1);
	}

	if (nx > maxnx) maxnx = nx;
	if (ny > maxny) maxny = ny;

	/* Build cube of negated y's. */
	ycube = DD_TRUE(dd);
	Cudd_Ref(ycube);
	for (i = maxny - 1; i >= 0; i--) {
	    DdNode *tmpp;
	    tmpp = Cudd_bddAnd(dd,Cudd_Not(dd->vars[y[i]->index]),ycube);
	    if (tmpp == NULL) exit(2);
	    Cudd_Ref(tmpp);
	    Cudd_RecursiveDeref(dd,ycube);
	    ycube = tmpp;
	}
	/* Initialize vectors of BDD variables used by priority func. */
	xvars = ALLOC(DdNode *, nx);
	if (xvars == NULL) exit(2);
	for (i = 0; i < nx; i++) {
	    xvars[i] = dd->vars[x[i]->index];
	}
	yvars = ALLOC(DdNode *, ny);
	if (yvars == NULL) exit(2);
	for (i = 0; i < ny; i++) {
	    yvars[i] = dd->vars[y[i]->index];
	}

	/* Clean up */
	for (i=0; i < maxnx; i++) {
	    Cudd_RecursiveDeref(dd, x[i]);
	    Cudd_RecursiveDeref(dd, xn[i]);
	}
	FREE(x);
	FREE(xn);
	for (i=0; i < maxny; i++) {
	    Cudd_RecursiveDeref(dd, y[i]);
	    Cudd_RecursiveDeref(dd, yn_[i]);
	}
	FREE(y);
	FREE(yn_);

	if (pr>0) {(void) printf(":1: M"); Cudd_PrintDebug(dd,M,nx+ny,pr);}

	if (pr>0) (void) printf(":2: time to read the matrix = %s\n",
		    util_print_time(util_cpu_time() - lapTime));

	C = Cudd_addBddPattern(dd, M);
	if (C == 0) exit(2);
	Cudd_Ref(C);
	if (pr>0) {(void) printf(":3: C"); Cudd_PrintDebug(dd,C,nx+ny,pr);}

	/* Test iterators. */
	retval = testIterators(dd,M,C,pr);
	if (retval == 0) exit(2);

	cuddCacheProfile(dd,stdout);

	/* Test XOR */
	retval = testXor(dd,C,pr,nx+ny);
	if (retval == 0) exit(2);

	/* Test Hamming distance functions. */
	retval = testHamming(dd,C,pr);
	if (retval == 0) exit(2);

	/* Test selection functions. */
	CP = Cudd_CProjection(dd,C,ycube);
	if (CP == NULL) exit(2);
	Cudd_Ref(CP);
	if (pr>0) {(void) printf("ycube"); Cudd_PrintDebug(dd,ycube,nx+ny,pr);}
	if (pr>0) {(void) printf("CP"); Cudd_PrintDebug(dd,CP,nx+ny,pr);}

	if (nx == ny) {
	    CPr = Cudd_PrioritySelect(dd,C,xvars,yvars,(DdNode **)NULL,
		(DdNode *)NULL,ny,Cudd_Xgty);
	    if (CPr == NULL) exit(2);
	    Cudd_Ref(CPr);
	    if (pr>0) {(void) printf(":4: CPr"); Cudd_PrintDebug(dd,CPr,nx+ny,pr);}
	    if (CP != CPr) {
		(void) printf("CP != CPr!\n");
	    }
	    Cudd_RecursiveDeref(dd, CPr);
	}
	FREE(xvars); FREE(yvars);

	Cudd_RecursiveDeref(dd, CP);
	Cudd_RecursiveDeref(dd, ycube);

	/* Test functions for essential variables. */
	ess = Cudd_FindEssential(dd,C);
	if (ess == NULL) exit(2);
	Cudd_Ref(ess);
	if (pr>0) {(void) printf(":4: ess"); Cudd_PrintDebug(dd,ess,nx+ny,pr);}
	Cudd_RecursiveDeref(dd, ess);

	/* Test functions for shortest paths. */
	shortP = Cudd_ShortestPath(dd, M, NULL, NULL, &length);
	if (shortP == NULL) exit(2);
	Cudd_Ref(shortP);
	if (pr>0) {
	    (void) printf(":5: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr);
	}
	/* Test functions for largest cubes. */
	largest = Cudd_LargestCube(dd, Cudd_Not(C), &length);
	if (largest == NULL) exit(2);
	Cudd_Ref(largest);
	if (pr>0) {
	    (void) printf(":5b: largest");
	    Cudd_PrintDebug(dd,largest,nx+ny,pr);
	}
	Cudd_RecursiveDeref(dd, largest);

	/* Test Cudd_addEvalConst and Cudd_addIteConstant. */
	shortA = Cudd_BddToAdd(dd,shortP);
	if (shortA == NULL) exit(2);
	Cudd_Ref(shortA);
	Cudd_RecursiveDeref(dd, shortP);
	constN = Cudd_addEvalConst(dd,shortA,M);
	if (constN == DD_NON_CONSTANT) exit(2);
	if (Cudd_addIteConstant(dd,shortA,M,constN) != constN) exit(2);
	if (pr>0) {(void) printf("The value of M along the chosen shortest path is %g\n", cuddV(constN));}
	Cudd_RecursiveDeref(dd, shortA);

	shortP = Cudd_ShortestPath(dd, C, NULL, NULL, &length);
	if (shortP == NULL) exit(2);
	Cudd_Ref(shortP);
	if (pr>0) {
	    (void) printf(":6: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr);
	}

	/* Test Cudd_bddIteConstant and Cudd_bddLeq. */
	if (!Cudd_bddLeq(dd,shortP,C)) exit(2);
	if (Cudd_bddIteConstant(dd,Cudd_Not(shortP),_true,C) != _true) exit(2);
	Cudd_RecursiveDeref(dd, shortP);

	if (profile) {
	    retval = cuddHeapProfile(dd);
	}

	size = dd->size;

	if (pr>0) {
	    (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd));
	}

	/* Reorder if so requested. */
        if (approach != CUDD_REORDER_NONE) {
#ifndef DD_STATS
	    retval = Cudd_EnableReorderingReporting(dd);
	    if (retval == 0) {
		(void) fprintf(stderr,"Error reported by Cudd_EnableReorderingReporting\n");
		exit(3);
	    }
#endif
#ifdef DD_DEBUG
	    retval = Cudd_DebugCheck(dd);
	    if (retval != 0) {
		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
		exit(3);
	    }
	    retval = Cudd_CheckKeys(dd);
	    if (retval != 0) {
		(void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n");
		exit(3);
	    }
#endif
	    retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5);
	    if (retval == 0) {
		(void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n");
		exit(3);
	    }
#ifndef DD_STATS
	    retval = Cudd_DisableReorderingReporting(dd);
	    if (retval == 0) {
		(void) fprintf(stderr,"Error reported by Cudd_DisableReorderingReporting\n");
		exit(3);
	    }
#endif
#ifdef DD_DEBUG
	    retval = Cudd_DebugCheck(dd);
	    if (retval != 0) {
		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
		exit(3);
	    }
	    retval = Cudd_CheckKeys(dd);
	    if (retval != 0) {
		(void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n");
		exit(3);
	    }
#endif
	    if (approach == CUDD_REORDER_SYMM_SIFT ||
	    approach == CUDD_REORDER_SYMM_SIFT_CONV) {
		Cudd_SymmProfile(dd,0,dd->size-1);
	    }

	    if (pr>0) {
		(void) printf("Average distance: %g\n", Cudd_AverageDistance(dd));
	    }

	    if (keepperm) {
		/* Print variable permutation. */
		(void) printf("Variable Permutation:");
		for (i=0; i<size; i++) {
		    if (i%20 == 0) (void) printf("\n");
		    (void) printf("%d ", dd->invperm[i]);
		}
		(void) printf("\n");
		(void) printf("Inverse Permutation:");
		for (i=0; i<size; i++) {
		    if (i%20 == 0) (void) printf("\n");
		    (void) printf("%d ", dd->perm[i]);
		}
		(void) printf("\n");
	    }

	    if (pr>0) {(void) printf("M"); Cudd_PrintDebug(dd,M,nx+ny,pr);}

	    if (profile) {
		retval = cuddHeapProfile(dd);
	    }

	}

	/* Dump DDs of C and M if so requested. */
	if (dfile != NULL) {
	    dfunc[0] = C;
	    dfunc[1] = M;
	    if (blifOrDot == 1) {
		/* Only dump C because blif cannot handle ADDs */
		retval = Cudd_DumpBlif(dd,1,dfunc,NULL,(char **)onames,
				       NULL,dfp);
	    } else {
		retval = Cudd_DumpDot(dd,2,dfunc,NULL,(char **)onames,dfp);
	    }
	    if (retval != 1) {
		(void) fprintf(stderr,"abnormal termination\n");
		exit(2);
	    }
	}

	Cudd_RecursiveDeref(dd, C);
	Cudd_RecursiveDeref(dd, M);

	if (clearcache) {
	    if (pr>0) {(void) printf("Clearing the cache... ");}
	    for (i = dd->cacheSlots - 1; i>=0; i--) {
		dd->cache[i].data = NIL(DdNode);
	    }
	    if (pr>0) {(void) printf("done\n");}
	}
	if (pr>0) {
	    (void) printf("Number of variables = %6d\t",dd->size);
	    (void) printf("Number of slots     = %6d\n",dd->slots);
	    (void) printf("Number of keys      = %6d\t",dd->keys);
	    (void) printf("Number of min dead  = %6d\n",dd->minDead);
	}

    } while (multiple && !feof(fp));

    fclose(fp);
    if (dfile != NULL) {
	fclose(dfp);
    }

    /* Second phase: experiment with Walsh matrices. */
    if (!testWalsh(dd,N,cmu,approach,pr)) {
	exit(2);
    }

    /* Check variable destruction. */
    assert(cuddDestroySubtables(dd,3));
    assert(Cudd_DebugCheck(dd) == 0);
    assert(Cudd_CheckKeys(dd) == 0);

    retval = Cudd_CheckZeroRef(dd);
    ok = retval != 0;  /* ok == 0 means O.K. */
    if (retval != 0) {
	(void) fprintf(stderr,
	    "%d non-zero DD reference counts after dereferencing\n", retval);
    }

    if (pr >= 0) {
	(void) Cudd_PrintInfo(dd,stdout);
    }

    Cudd_Quit(dd);

#ifdef MNEMOSYNE
    mnem_writestats();
#endif

    if (pr>0) (void) printf("total time = %s\n",
		util_print_time(util_cpu_time() - startTime));

    if (pr >= 0) util_print_cpu_stats(stdout);
    exit(ok);
    /* NOTREACHED */

} /* end of main */
Esempio n. 2
0
int main( int argc, char **argv )
{
    FILE *fp;
    FILE *stdin_backup = NULL;
    bool help_flag = False;
    bool ptdump_flag = False;
    bool logging_flag = False;
    unsigned char verbose = 0;
    int input_index = -1;
    int output_file_index = -1;  /* For command-line flag "-o". */
    char dumpfilename[64];

    int i, j, var_index;
    ptree_t *tmppt;  /* General purpose temporary ptree pointer */
    int horizon = -1;

    DdNode *W, *etrans, *strans, **sgoals, **egoals;

    DdManager *manager;
    DdNode *T = NULL;
    anode_t *strategy = NULL;
    int num_env, num_sys;
    int original_num_env, original_num_sys;

    int max_sim_it;  /* Number of simulation iterations */
    anode_t *play;
    vartype *init_state;
    int *init_state_ints = NULL;
    char *all_vars = NULL, *metric_vars = NULL;
    int *offw, num_vars;
    int init_state_acc;  /* Accumulate components of initial state
                            before expanding into a (bool) bitvector. */

    /* Look for flags in command-line arguments. */
    for (i = 1; i < argc; i++) {
        if (argv[i][0] == '-') {
            if (argv[i][1] == 'h') {
                help_flag = True;
            } else if (argv[i][1] == 'V') {
                printf( "grjit (experiment-related program, distributed with"
                        " gr1c v" GR1C_VERSION ")\n\n" GR1C_COPYRIGHT "\n" );
                return 0;
            } else if (argv[i][1] == 'v') {
                verbose = 1;
                j = 2;
                /* Only support up to "level 2" of verbosity */
                while (argv[i][j] == 'v' && j <= 2) {
                    verbose++;
                    j++;
                }
            } else if (argv[i][1] == 'l') {
                logging_flag = True;
            } else if (argv[i][1] == 'p') {
                ptdump_flag = True;
            } else if (argv[i][1] == 'm') {
                if (i == argc-1) {
                    fprintf( stderr, "Invalid flag given. Try \"-h\".\n" );
                    return 1;
                }
                all_vars = strtok( argv[i+1], "," );
                max_sim_it = strtol( all_vars, NULL, 10 );
                all_vars = strtok( NULL, "," );
                if (all_vars == NULL) {
                    fprintf( stderr, "Invalid use of -m flag.\n" );
                    return 1;
                }
                metric_vars = strdup( all_vars );
                if (max_sim_it >= 0) {
                    all_vars = strtok( NULL, "," );
                    if (all_vars == NULL) {
                        fprintf( stderr, "Invalid use of -m flag.\n" );
                        return 1;
                    }
                    init_state_acc = read_state_str( all_vars,
                                                     &init_state_ints, -1 );
                    all_vars = strtok( NULL, "," );
                    if (all_vars == NULL) {
                        horizon = -1;  /* The horizon was not given. */
                    } else {
                        horizon = strtol( all_vars, NULL, 10 );
                        if (horizon < 1) {
                            fprintf( stderr,
                                     "Invalid use of -m flag.  Horizon must"
                                     " be positive.\n" );
                            return 1;
                        }
                    }
                }
                all_vars = NULL;
                i++;
            } else if (argv[i][1] == 'o') {
                if (i == argc-1) {
                    fprintf( stderr, "Invalid flag given. Try \"-h\".\n" );
                    return 1;
                }
                output_file_index = i+1;
                i++;
            } else {
                fprintf( stderr, "Invalid flag given. Try \"-h\".\n" );
                return 1;
            }
        } else if (input_index < 0) {
            /* Use first non-flag argument as filename whence to read
               specification. */
            input_index = i;
        }
    }

    if (help_flag) {
        /* Split among printf() calls to conform with ISO C90 string length */
        printf( "Usage: %s [-hVvlp] [-m ARG1,ARG2,...] [-o FILE] [FILE]\n\n"
                "  -h          this help message\n"
                "  -V          print version and exit\n"
                "  -v          be verbose; use -vv to be more verbose\n"
                "  -l          enable logging\n"
                "  -p          dump parse trees to DOT files, and echo formulas to screen\n"
                "  -o FILE     output results to FILE, rather than stdout (default)\n", argv[0] );
        printf( "  -m ARG1,... run simulation using comma-separated list of arguments:\n"
                "                ARG1 is the max simulation duration; -1 to only compute horizon;\n"
                "                ARG2 is a space-separated list of metric variables;\n"
                "                ARG3 is a space-separated list of initial values;\n"
                "                    ARG3 is ignored and may be omitted if ARG1 equals -1.\n"
                "                ARG4 is the horizon, if provided; otherwise compute it.\n" );
        return 1;
    }

    if (logging_flag) {
        openlogfile( NULL );  /* Use default filename prefix */
        /* Only change verbosity level if user did not specify it */
        if (verbose == 0)
            verbose = 1;
    } else {
        setlogstream( stdout );
        setlogopt( LOGOPT_NOTIME );
    }
    if (verbose > 0)
        logprint( "Running with verbosity level %d.", verbose );

    /* If filename for specification given at command-line, then use
       it.  Else, read from stdin. */
    if (input_index > 0) {
        fp = fopen( argv[input_index], "r" );
        if (fp == NULL) {
            perror( "grjit, fopen" );
            return -1;
        }
        stdin_backup = stdin;
        stdin = fp;
    }

    /* Parse the specification. */
    if (verbose)
        logprint( "Parsing input..." );
    SPC_INIT( spc );
    if (yyparse())
        return -1;
    if (verbose)
        logprint( "Done." );
    if (stdin_backup != NULL) {
        stdin = stdin_backup;
    }

    /* Close input file, if opened. */
    if (input_index > 0)
        fclose( fp );

    /* Treat deterministic problem in which ETRANS or EINIT is omitted. */
    if (spc.evar_list == NULL) {
        if (spc.et_array_len == 0) {
            spc.et_array_len = 1;
            spc.env_trans_array = malloc( sizeof(ptree_t *) );
            if (spc.env_trans_array == NULL) {
                perror( "gr1c, malloc" );
                return -1;
            }
            *spc.env_trans_array = init_ptree( PT_CONSTANT, NULL, 1 );
        }
        if (spc.env_init == NULL)
            spc.env_init = init_ptree( PT_CONSTANT, NULL, 1 );
    }

    /* Number of variables, before expansion of those that are nonboolean */
    original_num_env = tree_size( spc.evar_list );
    original_num_sys = tree_size( spc.svar_list );

    /* Build list of variable names if needed for simulation, storing
       the result as a string in all_vars */
    if (max_sim_it >= 0) {
        /* At this point, init_state_acc should contain the number of
           integers read by read_state_str() during
           command-line argument parsing. */
        if (init_state_acc != original_num_env+original_num_sys) {
            fprintf( stderr,
                     "Number of initial values given does not match number"
                     " of problem variables.\n" );
            return 1;
        }

        num_vars = 0;
        tmppt = spc.evar_list;
        while (tmppt) {
            num_vars += strlen( tmppt->name )+1;
            tmppt = tmppt->left;
        }
        tmppt = spc.svar_list;
        while (tmppt) {
            num_vars += strlen( tmppt->name )+1;
            tmppt = tmppt->left;
        }
        all_vars = malloc( num_vars*sizeof(char) );
        if (all_vars == NULL) {
            perror( "main, malloc" );
            return -1;
        }
        i = 0;
        tmppt = spc.evar_list;
        while (tmppt) {
            strncpy( all_vars+i, tmppt->name, num_vars-i );
            i += strlen( tmppt->name )+1;
            *(all_vars+i-1) = ' ';
            tmppt = tmppt->left;
        }
        tmppt = spc.svar_list;
        while (tmppt) {
            strncpy( all_vars+i, tmppt->name, num_vars-i );
            i += strlen( tmppt->name )+1;
            *(all_vars+i-1) = ' ';
            tmppt = tmppt->left;
        }
        *(all_vars+i-1) = '\0';
        if (verbose)
            logprint( "String of all variables found to be \"%s\"", all_vars );
    }


    if (ptdump_flag) {
        tree_dot_dump( spc.env_init, "env_init_ptree.dot" );
        tree_dot_dump( spc.sys_init, "sys_init_ptree.dot" );

        for (i = 0; i < spc.et_array_len; i++) {
            snprintf( dumpfilename, sizeof(dumpfilename),
                      "env_trans%05d_ptree.dot", i );
            tree_dot_dump( *(spc.env_trans_array+i), dumpfilename );
        }
        for (i = 0; i < spc.st_array_len; i++) {
            snprintf( dumpfilename, sizeof(dumpfilename),
                      "sys_trans%05d_ptree.dot", i );
            tree_dot_dump( *(spc.sys_trans_array+i), dumpfilename );
        }

        if (spc.num_egoals > 0) {
            for (i = 0; i < spc.num_egoals; i++) {
                snprintf( dumpfilename, sizeof(dumpfilename),
                         "env_goal%05d_ptree.dot", i );
                tree_dot_dump( *(spc.env_goals+i), dumpfilename );
            }
        }
        if (spc.num_sgoals > 0) {
            for (i = 0; i < spc.num_sgoals; i++) {
                snprintf( dumpfilename, sizeof(dumpfilename),
                         "sys_goal%05d_ptree.dot", i );
                tree_dot_dump( *(spc.sys_goals+i), dumpfilename );
            }
        }

        var_index = 0;
        printf( "Environment variables (indices; domains): " );
        if (spc.evar_list == NULL) {
            printf( "(none)" );
        } else {
            tmppt = spc.evar_list;
            while (tmppt) {
                if (tmppt->value == 0) {  /* Boolean */
                    if (tmppt->left == NULL) {
                        printf( "%s (%d; bool)", tmppt->name, var_index );
                    } else {
                        printf( "%s (%d; bool), ", tmppt->name, var_index);
                    }
                } else {
                    if (tmppt->left == NULL) {
                        printf( "%s (%d; {0..%d})",
                                tmppt->name, var_index, tmppt->value );
                    } else {
                        printf( "%s (%d; {0..%d}), ",
                                tmppt->name, var_index, tmppt->value );
                    }
                }
                tmppt = tmppt->left;
                var_index++;
            }
        }
        printf( "\n\n" );

        printf( "System variables (indices; domains): " );
        if (spc.svar_list == NULL) {
            printf( "(none)" );
        } else {
            tmppt = spc.svar_list;
            while (tmppt) {
                if (tmppt->value == 0) {  /* Boolean */
                    if (tmppt->left == NULL) {
                        printf( "%s (%d; bool)", tmppt->name, var_index );
                    } else {
                        printf( "%s (%d; bool), ", tmppt->name, var_index );
                    }
                } else {
                    if (tmppt->left == NULL) {
                        printf( "%s (%d; {0..%d})",
                                tmppt->name, var_index, tmppt->value );
                    } else {
                        printf( "%s (%d; {0..%d}), ",
                                tmppt->name, var_index, tmppt->value );
                    }
                }
                tmppt = tmppt->left;
                var_index++;
            }
        }
        printf( "\n\n" );

        print_GR1_spec( spc.evar_list, spc.svar_list, spc.env_init, spc.sys_init,
                        spc.env_trans_array, spc.et_array_len,
                        spc.sys_trans_array, spc.st_array_len,
                        spc.env_goals, spc.num_egoals, spc.sys_goals, spc.num_sgoals, stdout );
    }

    if (expand_nonbool_GR1( spc.evar_list, spc.svar_list, &spc.env_init, &spc.sys_init,
                            &spc.env_trans_array, &spc.et_array_len,
                            &spc.sys_trans_array, &spc.st_array_len,
                            &spc.env_goals, spc.num_egoals, &spc.sys_goals, spc.num_sgoals,
                            verbose ) < 0)
        return -1;
    spc.nonbool_var_list = expand_nonbool_variables( &spc.evar_list, &spc.svar_list,
                                                     verbose );

    if (spc.et_array_len > 1) {
        spc.env_trans = merge_ptrees( spc.env_trans_array, spc.et_array_len, PT_AND );
    } else if (spc.et_array_len == 1) {
        spc.env_trans = *spc.env_trans_array;
    } else {
        fprintf( stderr,
                 "Syntax error: GR(1) specification is missing environment"
                 " transition rules.\n" );
        return -1;
    }
    if (spc.st_array_len > 1) {
        spc.sys_trans = merge_ptrees( spc.sys_trans_array, spc.st_array_len, PT_AND );
    } else if (spc.st_array_len == 1) {
        spc.sys_trans = *spc.sys_trans_array;
    } else {
        fprintf( stderr,
                 "Syntax error: GR(1) specification is missing system"
                 " transition rules.\n" );
        return -1;
    }

    if (verbose > 1)
        /* Dump the spec to show results of conversion (if any). */
        print_GR1_spec( spc.evar_list, spc.svar_list, spc.env_init, spc.sys_init,
                        spc.env_trans_array, spc.et_array_len,
                        spc.sys_trans_array, spc.st_array_len,
                        spc.env_goals, spc.num_egoals, spc.sys_goals, spc.num_sgoals, NULL );


    num_env = tree_size( spc.evar_list );
    num_sys = tree_size( spc.svar_list );

    manager = Cudd_Init( 2*(num_env+num_sys),
                         0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
    Cudd_SetMaxCacheHard( manager, (unsigned int)-1 );
    Cudd_AutodynEnable( manager, CUDD_REORDER_SAME );

    T = check_realizable( manager, EXIST_SYS_INIT, verbose );
    if (verbose) {
        if (T != NULL) {
            logprint( "Realizable." );
        } else {
            logprint( "Not realizable." );
        }
    }

    if (T != NULL) { /* Print measure data and simulate. */
        if (horizon < 0) {
            if (verbose)
                logprint( "Computing horizon with metric variables: %s",
                          metric_vars );
            horizon = compute_horizon( manager, &W, &etrans, &strans, &sgoals,
                                       metric_vars, verbose );
            logprint( "horizon: %d", horizon );
            if (getlogstream() != stdout)
                printf( "horizon: %d\n", horizon );
        } else {
            W = compute_winning_set_saveBDDs( manager, &etrans, &strans,
                                              &egoals, &sgoals, verbose );
            if (verbose)
                logprint( "Using given horizon: %d", horizon );
        }

        if (max_sim_it >= 0 && horizon > -1) {
            /* Compute variable offsets and use it to get the initial
               state as a bitvector */
            offw = get_offsets( all_vars, &num_vars );
            if (num_vars != original_num_env+original_num_sys) {
                fprintf( stderr,
                         "Error while computing bitwise variable offsets.\n" );
                return -1;
            }
            free( all_vars );
            init_state_acc = 0;
            if (verbose) {
                logprint_startline();
                logprint_raw( "initial state for simulation:" );
            }
            for (i = 0; i < original_num_env+original_num_sys; i++) {
                if (verbose)
                    logprint_raw( " %d", *(init_state_ints+i) );
                init_state_acc += *(init_state_ints+i) << *(offw + 2*i);
            }
            if (verbose)
                logprint_endline();
            free( offw );
            init_state = int_to_bitvec( init_state_acc, num_env+num_sys );
            if (init_state == NULL)
                return -1;

            play = sim_rhc( manager, W, etrans, strans, sgoals, metric_vars,
                            horizon, init_state, max_sim_it, verbose );
            if (play == NULL) {
                fprintf( stderr,
                         "Error while attempting receding horizon"
                         " simulation.\n" );
                return -1;
            }
            free( init_state );
            logprint( "play length: %d", aut_size( play ) );
            tmppt = spc.nonbool_var_list;
            while (tmppt) {
                aut_compact_nonbool( play, spc.evar_list, spc.svar_list,
                                     tmppt->name, tmppt->value );
                tmppt = tmppt->left;
            }

            num_env = tree_size( spc.evar_list );
            num_sys = tree_size( spc.svar_list );

            /* Open output file if specified; else point to stdout. */
            if (output_file_index >= 0) {
                fp = fopen( argv[output_file_index], "w" );
                if (fp == NULL) {
                    perror( "grjit, fopen" );
                    return -1;
                }
            } else {
                fp = stdout;
            }

            /* Print simulation trace */
            dump_simtrace( play, spc.evar_list, spc.svar_list, fp );
            if (fp != stdout)
                fclose( fp );
        }


        Cudd_RecursiveDeref( manager, W );
        Cudd_RecursiveDeref( manager, etrans );
        Cudd_RecursiveDeref( manager, strans );
    }

    /* Clean-up */
    free( metric_vars );
    delete_tree( spc.evar_list );
    delete_tree( spc.svar_list );
    delete_tree( spc.env_init );
    delete_tree( spc.sys_init );
    delete_tree( spc.env_trans );
    delete_tree( spc.sys_trans );
    for (i = 0; i < spc.num_egoals; i++)
        delete_tree( *(spc.env_goals+i) );
    if (spc.num_egoals > 0)
        free( spc.env_goals );
    for (i = 0; i < spc.num_sgoals; i++)
        delete_tree( *(spc.sys_goals+i) );
    if (spc.num_sgoals > 0)
        free( spc.sys_goals );
    if (T != NULL)
        Cudd_RecursiveDeref( manager, T );
    if (strategy)
        delete_aut( strategy );
    if (verbose > 1)
        logprint( "Cudd_CheckZeroRef -> %d", Cudd_CheckZeroRef( manager ) );
    Cudd_Quit(manager);
    if (logging_flag)
        closelogfile();

    /* Return 0 if realizable, -1 if not realizable. */
    if (T != NULL) {
        return 0;
    } else {
        return -1;
    }

    return 0;
}
Esempio n. 3
0
int main(int argc, char** argv) {
  unsigned int i;
  Biddy_Boolean complete;
  Biddy_Edge tmp;
  Biddy_Edge r1,r2;
  unsigned int n1,n2;
  char *userinput;

#ifdef USA_YES
  unsigned int usaSize = 0;
  unsigned int **usaEdge;
  unsigned int *usaOrder;
  char *usaCodes;
  Biddy_Edge *usaState;
  Biddy_Edge *usaGraph;
#endif

#ifdef EUROPE_YES
  unsigned int europeSize = 0;
  unsigned int **europeEdge;
  unsigned int *europeOrder;
  char *europeCodes;
  Biddy_Edge *europeState;
  Biddy_Edge *europeGraph;
#endif

  setbuf(stdout, NULL);

#ifdef USA_YES
  setDataUSA(&usaSize,&usaEdge,&usaOrder,&usaCodes);
#endif

#ifdef EUROPE_YES
  setDataEurope(&europeSize,&europeEdge,&europeOrder,&europeCodes);
#endif

#ifdef USE_BIDDY
  /* There is only one unique table in Biddy */
  /* There are three caches in Biddy */
  /* Unique table grows over the time */
  /* The max number of variables is hardcoded in biddyInt. h */
  /* biddyVariableTable.usaSize = BIDDYVARMAX = 2048 */
  /* The following constants are hardcoded in biddyMain.c */
  /* biddyIteCache.usaSize = MEDIUM_TABLE = 262143 */
  /* biddyEACache.usaSize = SMALL_TABLE = 65535 */
  /* biddyRCCache.usaSize = SMALL_TABLE = 65535 */
  /* DEFAULT INIT CALL: Biddy_Init() */
  Biddy_Init();
#endif

#ifdef USE_CUDD
  /* In CUDD each variable has its own subtable in the unique table */
  /* There is only one cache in CUDD */
  /* Subtables grow over the time, you can set limit for fast unique table growth */
  /* Cudd_SetLooseUpTo(manager,1048576) */
  /* Cache can grow over the time, you can set the max usaSize */
  /* Cudd_SetMaxCacheHard(manager,262144) */
  /* These two constants are hardcoded in v3.0.0 */
  /* CUDD_UNIQUE_SLOTS = 256 (default initial usaSize of each subtable) */
  /* CUDD_CACHE_SLOTS = 262144 (default initial usaSize of cache table) */
  /* DEFAULT INIT CALL: Cudd_Init(0,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0) */
  manager = Cudd_Init(0,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0);
  Cudd_SetMaxCacheHard(manager,262144);
#endif

#ifdef USA_YES
  usaGraph = (Biddy_Edge *) malloc(usaSize*sizeof(Biddy_Edge *));
  usaState = (Biddy_Edge *) malloc(usaSize*sizeof(Biddy_Edge *));
#endif

#ifdef EUROPE_YES
  europeGraph = (Biddy_Edge *) malloc(europeSize*sizeof(Biddy_Edge *));
  europeState = (Biddy_Edge *) malloc(europeSize*sizeof(Biddy_Edge *));
#endif

  i = 0;
  complete = FALSE;
  while (!complete) {
    complete = TRUE;
    tmp = Biddy_AddVariable();
#ifdef USA_YES
    if (i < usaSize) {
      usaState[usaOrder[i]] = tmp;
    }
    complete = complete && (i >= (usaSize-1));
#endif
#ifdef EUROPE_YES
    if (i < europeSize) {
      europeState[europeOrder[i]] = tmp;
    }
    complete = complete && (i >= (europeSize-1));
#endif
    i++;
  }

#ifdef USA_YES
  createGraph(usaSize,usaEdge,usaState,usaGraph);
#endif

#ifdef EUROPE_YES
  createGraph(europeSize,europeEdge,europeState,europeGraph);
#endif

#ifdef USE_BIDDY
  Biddy_Clean();
#endif

  r1 = Biddy_GetConstantZero();
  r2 = Biddy_GetConstantZero();
#ifdef USE_CUDD
  Cudd_Ref(r1);
  Cudd_Ref(r2);
#endif

#ifdef USA_YES
  if (!CALCULATE_KERNELS) {
    /* CALCULATING INDEPENDENCE SETS FOR USA */
#ifdef USE_CUDD
    Cudd_RecursiveDeref(manager,r1);
#endif
    r1 = calculateIndependence(usaSize,usaState,usaGraph);
  } else {
    /* CALCULATING KERNELS (MAXIMUM INDEPENDENCE SETS) FOR USA */
#ifdef USE_CUDD
    Cudd_RecursiveDeref(manager,r1);
#endif
    r1 = calculateKernels(usaSize,usaState,usaGraph);
  }
#ifdef USE_BIDDY
  Biddy_AddPersistentFormula((Biddy_String)"usa",r1);
  Biddy_Clean();
#endif
#ifdef USE_CUDD
  for (i=0; i<usaSize; i++) {
    Cudd_RecursiveDeref(manager,usaGraph[i]);
  }
#endif
#endif

#ifdef EUROPE_YES
  if (!CALCULATE_KERNELS) {
    /* CALCULATING INDEPENDENCE SETS FOR EUROPE */
#ifdef USE_CUDD
    Cudd_RecursiveDeref(manager,r2);
#endif
    r2 = calculateIndependence(europeSize,europeState,europeGraph);
  } else {
    /* CALCULATING KERNELS (MAXIMUM INDEPENDENCE SETS) FOR EUROPE */
#ifdef USE_CUDD
    Cudd_RecursiveDeref(manager,r2);
#endif
    r2 = calculateKernels(europeSize,europeState,europeGraph);
  }
#ifdef USE_BIDDY
  Biddy_AddPersistentFormula((Biddy_String)"europe",r2);
  Biddy_Clean();
#endif
#ifdef USE_CUDD
  for (i=0; i<europeSize; i++) {
    Cudd_RecursiveDeref(manager,europeGraph[i]);
  }
#endif
#endif

  userinput = strdup("...");
  while (userinput[0] != 'x') {

    /* We have problems with passing stdout in the case you compile this file */
    /* with MINGW and use biddy.dll generated with Visual Studio. */
    /* In such cases, please, use Biddy_PrintInfo(NULL) */
    if (userinput[0] == 'r') Biddy_PrintInfo(stdout);

    /* SIFTING  */
#ifdef USE_BIDDY
#ifdef CONVERGE
    if (userinput[0] == 's') Biddy_PurgeAndReorder(NULL,TRUE);
#ifdef USA_YES
    if (userinput[0] == 'u') Biddy_PurgeAndReorder(r1,TRUE);
#endif
#ifdef EUROPE_YES
    if (userinput[0] == 'e') Biddy_PurgeAndReorder(r2,TRUE);
#endif
#else
    if (userinput[0] == 's') Biddy_PurgeAndReorder(NULL,FALSE);
#ifdef USA_YES
    if (userinput[0] == 'u') Biddy_PurgeAndReorder(r1,FALSE);
#endif
#ifdef EUROPE_YES
    if (userinput[0] == 'e') Biddy_PurgeAndReorder(r2,FALSE);
#endif
#endif
#endif
#ifdef USE_CUDD
#ifdef CONVERGE
    if (userinput[0] == 's') Cudd_ReduceHeap(manager,CUDD_REORDER_SIFT_CONVERGE,0);
#else
    if (userinput[0] == 's') Cudd_ReduceHeap(manager,CUDD_REORDER_SIFT,0);
#endif
#endif
    n1 = Biddy_VariableNumber(r1);
    n2 = Biddy_VariableNumber(r2);
    if ((userinput[0] == 's')
#ifdef USA_YES
        || (userinput[0] == 'u')
#endif
#ifdef EUROPE_YES
        || (userinput[0] == 'e')
#endif
    ) {
#ifdef CONVERGE
      printf("(CONVERGING SIFTING");
#ifdef USE_BIDDY
      if (userinput[0] == 'u') {
        printf(" ON FUNCTION FOR USA");
      }
      if (userinput[0] == 'e') {
        printf(" ON FUNCTION FOR EUROPE");
      }
#endif
      printf(") ");
#else
      printf("(SIFTING");
#ifdef USE_BIDDY
      if (userinput[0] == 'u') {
        printf(" ON FUNCTION FOR USA");
      }
      if (userinput[0] == 'e') {
        printf(" ON FUNCTION FOR EUROPE");
      }
#endif
      printf(") ");
#endif
    }

    printf("Resulting function r1/r2 depends on %u/%u variables.\n",n1,n2);
    printf("Resulting function r1/r2 has %.0f/%.0f minterms.\n",Biddy_CountMinterm(r1,n1),Biddy_CountMinterm(r2,n2));
#ifdef USE_BIDDY
    printf("BDD for resulting function r1/r2 has %u/%u nodes (%u/%u nodes if using complement edges).\n",
           Biddy_NodeNumberPlain(r1),Biddy_NodeNumberPlain(r2),Biddy_NodeNumber(r1),Biddy_NodeNumber(r2));
#endif
#ifdef USE_CUDD
    printf("BDD for resulting function r1/r2 has %u/%u nodes (using complement edges).\n",Biddy_NodeNumber(r1),Biddy_NodeNumber(r2));
#endif
#ifdef USE_BIDDY
    printf("Variable swaps performed so far: %u\n",Biddy_NodeTableSwapNumber());
#endif
#ifdef USE_CUDD
    printf("Variable swaps performed so far: %.0f\n",Cudd_ReadSwapSteps(manager));
#endif
#ifdef USA_YES
    printf("Order for USA: ");
    writeOrder(r1,usaCodes,usaOrder,usaSize);
#endif
#ifdef EUROPE_YES
    printf("Order for Europe: ");
    writeOrder(r2,europeCodes,europeOrder,europeSize);
#endif
#ifdef USE_BIDDY
    printf("E[x]it or [r]eport or ");
#ifdef CONVERGE
    printf("Converging sifting ");
#else
    printf("Sifting ");
#endif
#if (defined USA_YES) || (defined EUROPE_YES)
    printf("on [s]ystem or Sifting on function for");
#ifdef USA_YES
    printf(" [u]SA");
#endif
#ifdef EUROPE_YES
    printf(" [e]urope");
#endif
#endif
    printf(": ");
    if (!scanf("%s",userinput)) printf("ERROR\n");
#endif
#ifdef USE_CUDD
    printf("E[x]it or [r]eport or ");
#ifdef CONVERGE
    printf("Converging sifting ");
#else
    printf("Sifting ");
#endif
    printf("on [s]ystem: ");
    if (!scanf("%s",userinput)) printf("ERROR\n");
#endif
  }

  free(userinput);

  /* EXIT */
#ifdef USE_BIDDY
  Biddy_Exit();
#endif
#ifdef USE_CUDD
  Cudd_RecursiveDeref(manager,r1);
  Cudd_RecursiveDeref(manager,r2);
  printf("CUDD: nodes with non-zero reference counts: %d\n",Cudd_CheckZeroRef(manager));
  Cudd_Quit(manager);
#endif

  return 0;
}
Esempio n. 4
0
/**
 * @brief Basic test of timeout handler.
 *
 * @details Sets a short timeout and then tries to build a function
 * with a large BDD.  Strives to avoid leaking nodes.
 *
 * @return 0 if successful; -1 otherwise.
 */
static int
testTimeout(int verbosity)
{
    DdManager *dd;
    /* Declare these "volatile" to prevent clobbering by longjmp. */
    DdNode * volatile f;
    DdNode * volatile clause = NULL;
    DdNode * var1, * var2;
    int i, ret, count;
    int const N = 20; /* half the number of variables in f */
    unsigned long timeout = 100UL; /* in milliseconds */
    jmp_buf timeoutEnv;

    dd = Cudd_Init(0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0);
    if (!dd) {
        if (verbosity) {
            printf("initialization failed\n");
        }
        return -1;
    }

    /* Set up timeout handling. */
    if (setjmp(timeoutEnv) > 0) {
        if (verbosity) {
            printf("caught timeout\n");
        }
        /* The nodes of clause may be leaked if the timeout was
         * detected while conjoining the clause to f.  We set
         * clause to NULL when it's not in use to be able to
         * detect this case.
         */
        if (clause)
            Cudd_RecursiveDeref(dd, clause);
        goto finally;
    }
    (void) Cudd_RegisterTimeoutHandler(dd, timeoutHandler, (void *) &timeoutEnv);
    (void) Cudd_SetTimeLimit(dd, timeout);

    /* Try to build function.  This is expected to run out of time. */
    f = Cudd_ReadOne(dd);
    Cudd_Ref(f);
    for (i = 0; i < N; i++) {
        DdNode * tmp;
        var1 = Cudd_bddIthVar(dd, i);
        if (!var1) {
            if (verbosity) {
                printf("computation failed\n");
                return -1;
            }
        }
        var2 = Cudd_bddIthVar(dd, i+N);
        if (!var2) {
            if (verbosity) {
                printf("computation failed\n");
                return -1;
            }
        }
        clause = Cudd_bddOr(dd, var1, var2);
        if (!clause) {
            if (verbosity) {
                printf("computation failed\n");
            }
            return -1;
        }
        Cudd_Ref(clause);
        tmp = Cudd_bddAnd(dd, f, clause);
        if (!tmp) {
            if (verbosity) {
                printf("computation failed\n");
            }
            return -1;
        }
        Cudd_Ref(tmp);
        Cudd_RecursiveDeref(dd, clause);
        clause = NULL;
        Cudd_RecursiveDeref(dd, f);
        f = tmp;
    }
    if (verbosity > 1) {
        Cudd_bddPrintCover(dd, f, f);
    }

finally:
    if (verbosity) {
        printf("so far");
        Cudd_PrintSummary(dd, f, 2*N, 0);
    }
    count = 0;
    for (i = 0; i < N-1; i += 2) {
        var1 = Cudd_bddIthVar(dd, i);
        if (!var1) {
            printf("computation failed\n");
            return -1;
        }
        var2 = Cudd_bddIthVar(dd, i+1);
        if (!var2) {
            printf("computation failed\n");
            return -1;
        }
        clause = Cudd_bddOr(dd, var1, var2);
        if (!clause) {
            printf("computation failed\n");
            return -1;
        }
        Cudd_Ref(clause);
        if (Cudd_bddLeq(dd, f, clause)) {
            count++;
        }
        Cudd_RecursiveDeref(dd, clause);
    }
    if (verbosity) {
        printf("f implies %d clauses\n", count);
    }
    Cudd_RecursiveDeref(dd, f);
    ret = Cudd_CheckZeroRef(dd);
    if (verbosity) {
        Cudd_PrintInfo(dd, stdout);
        if (ret != 0) {
            printf("%d non-zero references\n", ret);
        }
    }
    Cudd_Quit(dd);
    return 0;
}
Esempio n. 5
0
/**
 * @brief Basic test of long double and EPD minterm computation.
 * @return 0 if successful; -1 otherwise.
 */
static int
testLdbl(int verbosity)
{
    DdManager *dd;
    DdNode *f, *g;
    int i, ret;
    int const N = 12; /* half the number of variables */
    long double cnt;

    dd = Cudd_Init(2*N, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0);
    if (!dd) {
        if (verbosity) {
            printf("initialization failed\n");
        }
        return -1;
    }
    f = g = Cudd_ReadOne(dd);
    Cudd_Ref(f);
    Cudd_Ref(g);
    for (i = 0; i < N; i++) {
        DdNode *var1, *var2, *clause, *tmp;
        var1 = Cudd_bddIthVar(dd, i);
        var2 = Cudd_bddIthVar(dd, i+N);
        clause = Cudd_bddOr(dd, var1, var2);
        if (!clause) {
            Cudd_Quit(dd);
            return -1;
        }
        Cudd_Ref(clause);
        tmp = Cudd_bddAnd(dd, f, clause);
        if (!tmp) {
            Cudd_Quit(dd);
            return -1;
        }
        Cudd_Ref(tmp);
        Cudd_RecursiveDeref(dd, clause);
        Cudd_RecursiveDeref(dd, f);
        f = tmp;
        clause = Cudd_bddOr(dd, Cudd_Not(var1), Cudd_Not(var2));
        if (!clause) {
            Cudd_Quit(dd);
            return -1;
        }
        Cudd_Ref(clause);
        tmp = Cudd_bddAnd(dd, g, clause);
        if (!tmp) {
            Cudd_Quit(dd);
            return -1;
        }
        Cudd_Ref(tmp);
        Cudd_RecursiveDeref(dd, clause);
        Cudd_RecursiveDeref(dd, g);
        g = tmp;
    }
    if (verbosity) {
        printf("f");
        Cudd_PrintSummary(dd, f, 2*N, 0);
    }
    cnt = Cudd_LdblCountMinterm(dd, f, 2*N);
    if (verbosity) {
        printf("f has %Lg minterms\n", cnt);
    }
    if (verbosity) {
        printf("EPD count for f = ");
        ret = Cudd_EpdPrintMinterm(dd, f, 2*N);
        printf("\n");
        if (!ret) {
            printf("problem with EPD\n");
        }
    }
    Cudd_RecursiveDeref(dd, f);
    if (verbosity) {
        printf("g");
        Cudd_PrintSummary(dd, g, 2*N, 0);
    }
    cnt = Cudd_LdblCountMinterm(dd, g, 2*N);
    if (verbosity) {
        printf("g has %Lg minterms\n", cnt);
    }
    if (verbosity) {
        printf("EPD count for g = ");
        ret = Cudd_EpdPrintMinterm(dd, g, 2*N);
        printf("\n");
        if (!ret) {
            printf("problem with EPD\n");
        }
    }
    Cudd_RecursiveDeref(dd, g);
    ret = Cudd_CheckZeroRef(dd);
    if (verbosity && ret != 0) {
        printf("%d non-zero references\n", ret);
    }
    Cudd_Quit(dd);
    return 0;
}
Esempio n. 6
0
/**Function********************************************************************

  Synopsis    [Main program for ntr.]

  Description [Main program for ntr. Performs initialization. Reads command
  line options and network(s). Builds BDDs with reordering, and optionally
  does reachability analysis. Prints stats.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
int
main(
  int  argc,
  char ** argv)
{
    NtrOptions	*option;	/* options */
    FILE	*fp1;		/* first network file pointer */
    BnetNetwork	*net1 = NULL;	/* first network */
    FILE	*fp2;		/* second network file pointer */
    BnetNetwork	*net2 = NULL;	/* second network */
    DdManager	*dd;		/* pointer to DD manager */
    int		exitval;	/* return value of Cudd_CheckZeroRef */
    int		ok;		/* overall return value from main() */
    int		result;		/* stores the return value of functions */
    BnetNode	*node;		/* auxiliary pointer to network node */
    int		i;		/* loop index */
    int		j;		/* loop index */
    double	*signatures;	/* array of signatures */
    int		pr;		/* verbosity level */
    int		reencoded;	/* linear transformations attempted */

    /* Initialize. */
    option = mainInit();
    ntrReadOptions(argc,argv,option);
    pr = option->verb;
    reencoded = option->reordering == CUDD_REORDER_LINEAR ||
		option->reordering == CUDD_REORDER_LINEAR_CONVERGE ||
		option->autoMethod == CUDD_REORDER_LINEAR ||
		option->autoMethod == CUDD_REORDER_LINEAR_CONVERGE;
    /* Currently traversal requires global BDDs. Override whatever
    ** was specified for locGlob.
    */
    if (option->traverse == TRUE || option->envelope == TRUE ||
	option->scc == TRUE) {
	option->locGlob = BNET_GLOBAL_DD;
    }

    /* Read the first network... */
    fp1 = open_file(option->file1, "r");
    net1 = Bnet_ReadNetwork(fp1,pr);
    (void) fclose(fp1);
    if (net1 == NULL) {
	(void) fprintf(stderr,"Syntax error in %s.\n",option->file1);
	exit(2);
    }
    /* ... and optionally echo it to the standard output. */
    if (pr > 2) {
	Bnet_PrintNetwork(net1);
    }

    /* Read the second network... */
    if (option->verify == TRUE || option->second == TRUE ||
	option->clip > 0.0 || option->dontcares) {
	fp2 = open_file(option->file2, "r");
	net2 = Bnet_ReadNetwork(fp2,pr);
	(void) fclose(fp2);
	if (net2 == NULL) {
	    (void) fprintf(stderr,"Syntax error in %s.\n",option->file2);
	    exit(2);
	}
	/* ... and optionally echo it to the standard output. */
	if (pr > 2) {
	    Bnet_PrintNetwork(net2);
	}
    }

    /* Initialize manager. We start with 0 variables, because
    ** Ntr_buildDDs will create new variables rather than using
    ** whatever already exists.
    */
    dd = startCudd(option,net1->ninputs);
    if (dd == NULL) { exit(2); }

    /* Build the BDDs for the nodes of the first network. */
    result = Ntr_buildDDs(net1,dd,option,NULL);
    if (result == 0) { exit(2); }

    /* Build the BDDs for the nodes of the second network if requested. */
    if (option->verify == TRUE || option->second == TRUE ||
	option->clip > 0.0 || option->dontcares == TRUE) {
	char *nodesave = option->node;
	option->node = NULL;
	result = Ntr_buildDDs(net2,dd,option,net1);
	option->node = nodesave;
	if (result == 0) { exit(2); }
    }

    if (option->noBuild == TRUE) {
	Bnet_FreeNetwork(net1);
	if (option->verify == TRUE || option->second == TRUE ||
	    option->clip > 0.0) {
	    Bnet_FreeNetwork(net2);
	}
	freeOption(option);
	exit(0);
    }
    if (option->locGlob != BNET_LOCAL_DD) {
	/* Print the order before the final reordering. */
	(void) printf("Order before final reordering\n");
	result = Bnet_PrintOrder(net1,dd);
	if (result == 0) exit(2);
    }

    /* Perform final reordering */
    if (option->zddtest == FALSE) {
	result = reorder(net1,dd,option);
	if (result == 0) exit(2);

	/* Print final order. */
	if ((option->reordering != CUDD_REORDER_NONE || option->gaOnOff) &&
	    option->locGlob != BNET_LOCAL_DD) {
	    (void) printf("New order\n");
	    result = Bnet_PrintOrder(net1,dd);
	    if (result == 0) exit(2);
	}

	/* Print the re-encoded inputs. */
	if (pr >= 1 && reencoded == 1) {
	    for (i = 0; i < net1->npis; i++) {
		if (!st_lookup(net1->hash,net1->inputs[i],&node)) {
		    exit(2);
		}
		(void) fprintf(stdout,"%s:",node->name);
		Cudd_PrintDebug(dd,node->dd,Cudd_ReadSize(dd),pr);
	    }
	    for (i = 0; i < net1->nlatches; i++) {
		if (!st_lookup(net1->hash,net1->latches[i][1],&node)) {
		    exit(2);
		}
		(void) fprintf(stdout,"%s:",node->name);
		Cudd_PrintDebug(dd,node->dd,Cudd_ReadSize(dd),pr);
	    }
	    if (pr >= 3) {
		result = Cudd_PrintLinear(dd);
		if (result == 0) exit(2);
	    }
	}
    }

    /* Verify (combinational) equivalence. */
    if (option->verify == TRUE) {
	result = Ntr_VerifyEquivalence(dd,net1,net2,option);
	if (result == 0) {
	    (void) printf("Verification abnormally terminated\n");
	    exit(2);
	} else if (result == -1) {
	    (void) printf("Combinational verification failed\n");
	} else {
	    (void) printf("Verification succeeded\n");
	}
    }

    /* Traverse if requested and if the circuit is sequential. */
    result = Ntr_Trav(dd,net1,option);
    if (result == 0) exit(2);

    /* Traverse with trasitive closure. */
    result = Ntr_ClosureTrav(dd,net1,option);
    if (result == 0) exit(2);

    /* Compute outer envelope if requested and if the circuit is sequential. */
    if (option->envelope == TRUE && net1->nlatches > 0) {
	NtrPartTR *T;
	T = Ntr_buildTR(dd,net1,option,option->image);
	result = Ntr_Envelope(dd,T,NULL,option);
	Ntr_freeTR(dd,T);
    }

    /* Compute SCCs if requested and if the circuit is sequential. */
    result = Ntr_SCC(dd,net1,option);
    if (result == 0) exit(2);

    /* Test Constrain Decomposition. */
    if (option->partition == TRUE && net1->nlatches > 0) {
	NtrPartTR *T;
	DdNode *product;
	DdNode **decomp;
	int sharingSize;
	T = Ntr_buildTR(dd,net1,option,NTR_IMAGE_MONO);
	decomp = Cudd_bddConstrainDecomp(dd,T->part[0]);
	if (decomp == NULL) exit(2);
	sharingSize = Cudd_SharingSize(decomp, Cudd_ReadSize(dd));
	(void) fprintf(stdout, "Decomposition Size: %d components %d nodes\n",
		       Cudd_ReadSize(dd), sharingSize);
	product = Cudd_ReadOne(dd);
	Cudd_Ref(product);
	for (i = 0; i < Cudd_ReadSize(dd); i++) {
	    DdNode *intermediate = Cudd_bddAnd(dd, product, decomp[i]);
	    if (intermediate == NULL) {
		exit(2);
	    }
	    Cudd_Ref(intermediate);
	    Cudd_IterDerefBdd(dd, product);
	    product = intermediate;
	}
	if (product != T->part[0])
	    exit(2);
	Cudd_IterDerefBdd(dd, product);
	for (i = 0; i < Cudd_ReadSize(dd); i++) {
	    Cudd_IterDerefBdd(dd, decomp[i]);
	}
	FREE(decomp);
	Ntr_freeTR(dd,T);
    }

    /* Test char-to-vect conversion. */
    result = Ntr_TestCharToVect(dd,net1,option);
    if (result == 0) exit(2);

    /* Test extraction of two-literal clauses. */
    result = Ntr_TestTwoLiteralClauses(dd,net1,option);
    if (result == 0) exit(2);

    /* Test BDD minimization functions. */
    result = Ntr_TestMinimization(dd,net1,net2,option);
    if (result == 0) exit(2);

    /* Test density-related functions. */
    result = Ntr_TestDensity(dd,net1,option);
    if (result == 0) exit(2);

    /* Test decomposition functions. */
    result = Ntr_TestDecomp(dd,net1,option);
    if (result == 0) exit(2);

    /* Test cofactor estimation functions. */
    result = Ntr_TestCofactorEstimate(dd,net1,option);
    if (result == 0) exit(2);

    /* Test BDD clipping functions. */
    result = Ntr_TestClipping(dd,net1,net2,option);
    if (result == 0) exit(2);

    /* Test BDD equivalence and containment under DC functions. */
    result = Ntr_TestEquivAndContain(dd,net1,net2,option);
    if (result == 0) exit(2);

    /* Test BDD Cudd_bddClosestCube. */
    result = Ntr_TestClosestCube(dd,net1,option);
    if (result == 0) exit(2);

    /* Test ZDDs if requested. */
    if (option->stateOnly == FALSE && option->zddtest == TRUE) {
	result = Ntr_testZDD(dd,net1,option);
	if (result == 0)
	    (void) fprintf(stdout,"ZDD test failed.\n");
	result = Ntr_testISOP(dd,net1,option);
	if (result == 0)
	    (void) fprintf(stdout,"ISOP test failed.\n");
    }

    /* Compute maximum flow if requested and if the circuit is sequential. */
    if (option->maxflow == TRUE && net1->nlatches > 0) {
	result = Ntr_maxflow(dd,net1,option);
	if (result == 0)
	    (void) fprintf(stdout,"Maxflow computation failed.\n");
    }

    /* Compute shortest paths if requested and if the circuit is sequential. */
    if (option->shortPath != NTR_SHORT_NONE && net1->nlatches > 0) {
	result = Ntr_ShortestPaths(dd,net1,option);
	if (result == 0)
	    (void) fprintf(stdout,"Shortest paths computation failed.\n");
    }

    /* Compute output signatures if so requested. */
    if (option->signatures) {
	(void) printf("Positive cofactor measures\n");
	for (i = 0; i < net1->noutputs; i++) {
	    if (!st_lookup(net1->hash,net1->outputs[i],&node)) {
		exit(2);
	    }
	    signatures = Cudd_CofMinterm(dd, node->dd);
	    if (signatures) {
		(void) printf("%s:\n", node->name);
		for (j = 0; j < Cudd_ReadSize(dd); j++) {
		    if((j%5 == 0)&&i) (void) printf("\n");
		    (void) printf("%5d: %-#8.4g ", j, signatures[j]);
		}
		(void) printf("\n");
		FREE(signatures);
	    } else {
		(void) printf("Signature computation failed.\n");
	    }
	}
    }

    /* Dump BDDs if so requested. */
    if (option->bdddump && option->second == FALSE &&
	option->density == FALSE && option->decomp == FALSE &&
	option->cofest == FALSE && option->clip < 0.0 &&
	option->scc == FALSE) {
	(void) printf("Dumping BDDs to %s\n", option->dumpfile);
	if (option->node != NULL) {
	    if (!st_lookup(net1->hash,option->node,&node)) {
		exit(2);
	    }
	    result = Bnet_bddArrayDump(dd,net1,option->dumpfile,&(node->dd),
				       &(node->name),1,option->dumpFmt);
	} else {
	    result = Bnet_bddDump(dd, net1, option->dumpfile,
				  option->dumpFmt, reencoded);
	}
	if (result != 1) {
	    (void) printf("BDD dump failed.\n");
	}
    }

    /* Print stats and clean up. */
    if (pr >= 0) {
	result = Cudd_PrintInfo(dd,stdout);
	if (result != 1) {
	    (void) printf("Cudd_PrintInfo failed.\n");
	}
    }

#if defined(DD_DEBUG) && !defined(DD_NO_DEATH_ROW)
    (void) fprintf(dd->err,"%d empty slots in death row\n",
    cuddTimesInDeathRow(dd,NULL));
#endif
    (void) printf("Final size: %ld\n", Cudd_ReadNodeCount(dd));

    /* Dispose of node BDDs. */
    node = net1->nodes;
    while (node != NULL) {
	if (node->dd != NULL &&
	node->type != BNET_INPUT_NODE &&
	node->type != BNET_PRESENT_STATE_NODE) {
	    Cudd_IterDerefBdd(dd,node->dd);
	}
	node = node->next;
    }
    /* Dispose of network. */
    Bnet_FreeNetwork(net1);
    /* Do the same cleanup for the second network if it was created. */
    if (option->verify == TRUE || option->second == TRUE ||
	option->clip > 0.0 || option->dontcares == TRUE) {
	node = net2->nodes;
	while (node != NULL) {
	    if (node->dd != NULL &&
		node->type != BNET_INPUT_NODE &&
		node->type != BNET_PRESENT_STATE_NODE) {
		Cudd_IterDerefBdd(dd,node->dd);
	    }
	    node = node->next;
	}
	Bnet_FreeNetwork(net2);
    }

    /* Check reference counts: At this point we should have dereferenced
    ** everything we had, except in the case of re-encoding.
    */
    exitval = Cudd_CheckZeroRef(dd);
    ok = exitval != 0;  /* ok == 0 means O.K. */
    if (exitval != 0) {
	(void) fflush(stdout);
	(void) fprintf(stderr,
	    "%d non-zero DD reference counts after dereferencing\n", exitval);
    }

#ifdef DD_DEBUG
    Cudd_CheckKeys(dd);
#endif

    Cudd_Quit(dd);

    if (pr >= 0) (void) printf("total time = %s\n",
	    util_print_time(util_cpu_time() - option->initialTime));
    freeOption(option);
    if (pr >= 0) util_print_cpu_stats(stdout);

#ifdef MNEMOSYNE
    mnem_writestats();
#endif

    exit(ok);
    /* NOTREACHED */

} /* end of main */