Initial revision

This commit is contained in:
Alexandre Duret-Lutz 2003-05-05 10:57:53 +00:00
parent 1fa73989e0
commit cf5dd46350
67 changed files with 44947 additions and 0 deletions

593
buddy/src/bddio.c Normal file
View file

@ -0,0 +1,593 @@
/*========================================================================
Copyright (C) 1996-2002 by Jorn Lind-Nielsen
All rights reserved
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, reproduce, prepare derivative
works, distribute, and display this software and its documentation
for any purpose, provided that (1) the above copyright notice and
the following two paragraphs appear in all copies of the source code
and (2) redistributions, including without limitation binaries,
reproduce these notices in the supporting documentation. Substantial
modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided
that the new terms are clearly indicated in all files where they apply.
IN NO EVENT SHALL JORN LIND-NIELSEN, OR DISTRIBUTORS OF THIS
SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHORS OR ANY OF THE
ABOVE PARTIES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
JORN LIND-NIELSEN SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO
OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
========================================================================*/
/*************************************************************************
$Header: /Volumes/CVS/repository/spot/spot/buddy/src/bddio.c,v 1.1 2003/05/05 10:57:56 aduret Exp $
FILE: bddio.c
DESCR: File I/O routines for BDD package
AUTH: Jorn Lind
DATE: (C) june 1997
*************************************************************************/
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/stat.h>
#include "kernel.h"
static void bdd_printset_rec(FILE *, int, int *);
static void bdd_fprintdot_rec(FILE*, BDD);
static int bdd_save_rec(FILE*, int);
static int bdd_loaddata(FILE *);
static int loadhash_get(int);
static void loadhash_add(int, int);
static bddfilehandler filehandler;
typedef struct s_LoadHash
{
int key;
int data;
int first;
int next;
} LoadHash;
static LoadHash *lh_table;
static int lh_freepos;
static int lh_nodenum;
static int *loadvar2level;
/*=== PRINTING ========================================================*/
/*
NAME {* bdd\_file\_hook *}
SECTION {* kernel *}
SHORT {* Specifies a printing callback handler *}
PROTO {* bddfilehandler bdd_file_hook(bddfilehandler handler) *}
DESCR {* A printing callback handler for use with BDDs is used to
convert the BDD variable number into something readable by the
end user. Typically the handler will print a string name
instead of the number. A handler could look like this:
\begin{verbatim}
void printhandler(FILE *o, int var)
{
extern char **names;
fprintf(o, "%s", names[var]);
}
\end{verbatim}
\noindent
The handler can then be passed to BuDDy like this:
{\tt bdd\_file\_hook(printhandler)}.
No default handler is supplied. The argument {\tt handler} may be
NULL if no handler is needed. *}
RETURN {* The old handler *}
ALSO {* bdd\_printset, bdd\_strm\_hook, fdd\_file\_hook *}
*/
bddfilehandler bdd_file_hook(bddfilehandler handler)
{
bddfilehandler old = filehandler;
filehandler = handler;
return old;
}
/*
NAME {* bdd\_printall *}
EXTRA {* bdd\_fprintall *}
SECTION {* fileio *}
SHORT {* prints all used entries in the node table *}
PROTO {* void bdd_printall(void)
void bdd_fprintall(FILE* ofile) *}
DESCR {* Prints to either stdout or the file {\tt ofile} all the used
entries in the main node table. The format is:
\begin{Ill}
{\tt [Nodenum] Var/level Low High}
\end{Ill}
Where {\tt Nodenum} is the position in the node table and level
is the position in the current variable order. *}
ALSO {* bdd\_printtable, bdd\_printset, bdd\_printdot *}
*/
void bdd_printall(void)
{
bdd_fprintall(stdout);
}
void bdd_fprintall(FILE *ofile)
{
int n;
for (n=0 ; n<bddnodesize ; n++)
{
if (LOW(n) != -1)
{
fprintf(ofile, "[%5d - %2d] ", n, bddnodes[n].refcou);
if (filehandler)
filehandler(ofile, bddlevel2var[LEVEL(n)]);
else
fprintf(ofile, "%3d", bddlevel2var[LEVEL(n)]);
fprintf(ofile, ": %3d", LOW(n));
fprintf(ofile, " %3d", HIGH(n));
fprintf(ofile, "\n");
}
}
}
/*
NAME {* bdd\_printtable *}
EXTRA {* bdd\_fprinttable *}
SECTION {* fileio *}
SHORT {* prints the node table entries used by a BDD *}
PROTO {* void bdd_printtable(BDD r)
void bdd_fprinttable(FILE* ofile, BDD r) *}
DESCR {* Prints to either stdout or the file {\tt ofile} all the entries
in the main node table used by {\tt r}. The format is:
\begin{Ill}
{\tt [Nodenum] Var/level : Low High}
\end{Ill}
Where {\tt Nodenum} is the position in the node table and level
is the position in the current variable order. *}
ALSO {* bdd\_printall, bdd\_printset, bdd\_printdot *}
*/
void bdd_printtable(BDD r)
{
bdd_fprinttable(stdout, r);
}
void bdd_fprinttable(FILE *ofile, BDD r)
{
BddNode *node;
int n;
fprintf(ofile, "ROOT: %d\n", r);
if (r < 2)
return;
bdd_mark(r);
for (n=0 ; n<bddnodesize ; n++)
{
if (LEVEL(n) & MARKON)
{
node = &bddnodes[n];
LEVELp(node) &= MARKOFF;
fprintf(ofile, "[%5d] ", n);
if (filehandler)
filehandler(ofile, bddlevel2var[LEVELp(node)]);
else
fprintf(ofile, "%3d", bddlevel2var[LEVELp(node)]);
fprintf(ofile, ": %3d", LOWp(node));
fprintf(ofile, " %3d", HIGHp(node));
fprintf(ofile, "\n");
}
}
}
/*
NAME {* bdd\_printset *}
EXTRA {* bdd\_fprintset *}
SECTION {* fileio *}
SHORT {* prints the set of truth assignments specified by a BDD *}
PROTO {* bdd_printset(BDD r)
bdd_fprintset(FILE* ofile, BDD r) *}
DESCR {* Prints all the truth assignments for {\tt r} that would yield
it true. The format is:
\begin{Ill}
{\tt < $x_{1,1}:c_{1,1},\ldots,x_{1,n_1}:c_{1,n_1}$ >\\
< $x_{2,1}:c_{2,1},\ldots,x_{2,n_2}:c_{2,n_2}$ >\\
$\ldots$ \\
< $x_{N,1}:c_{N,1},\ldots,x_{N,n_3}:c_{N,n_3}$ > }
\end{Ill}
Where the $x$'s are variable numbers (and the position in the
current order) and the $c$'s are the
possible assignments to these. Each set of brackets designates
one possible assignment to the set of variables that make up the
BDD. All variables not shown are don't cares. It is possible to
specify a callback handler for printing of the variables using
{\tt bdd\_file\_hook} or {\tt bdd\_strm\_hook}. *}
ALSO {* bdd\_printall, bdd\_printtable, bdd\_printdot, bdd\_file\_hook, bdd\_strm\_hook *}
*/
void bdd_printset(BDD r)
{
bdd_fprintset(stdout, r);
}
void bdd_fprintset(FILE *ofile, BDD r)
{
int *set;
if (r < 2)
{
fprintf(ofile, "%s", r == 0 ? "F" : "T");
return;
}
if ((set=(int *)malloc(sizeof(int)*bddvarnum)) == NULL)
{
bdd_error(BDD_MEMORY);
return;
}
memset(set, 0, sizeof(int) * bddvarnum);
bdd_printset_rec(ofile, r, set);
free(set);
}
static void bdd_printset_rec(FILE *ofile, int r, int *set)
{
int n;
int first;
if (r == 0)
return;
else
if (r == 1)
{
fprintf(ofile, "<");
first = 1;
for (n=0 ; n<bddvarnum ; n++)
{
if (set[n] > 0)
{
if (!first)
fprintf(ofile, ", ");
first = 0;
if (filehandler)
filehandler(ofile, bddlevel2var[n]);
else
fprintf(ofile, "%d", bddlevel2var[n]);
fprintf(ofile, ":%d", (set[n]==2 ? 1 : 0));
}
}
fprintf(ofile, ">");
}
else
{
set[LEVEL(r)] = 1;
bdd_printset_rec(ofile, LOW(r), set);
set[LEVEL(r)] = 2;
bdd_printset_rec(ofile, HIGH(r), set);
set[LEVEL(r)] = 0;
}
}
/*
NAME {* bdd\_printdot *}
EXTRA {* bdd\_fprintdot *}
SECTION {* fileio *}
SHORT {* prints a description of a BDD in DOT format *}
PROTO {* void bdd_printdot(BDD r)
int bdd_fnprintdot(char* fname, BDD r)
void bdd_fprintdot(FILE* ofile, BDD r) *}
DESCR {* Prints a BDD in a format suitable for use with the graph
drawing program DOT to either stdout, a designated file
{\tt ofile} or the file named by {\tt fname}. In the last case
the file will be opened for writing, any previous contents
destroyed and then closed again. *}
ALSO {* bdd\_printall, bdd\_printtable, bdd\_printset *}
*/
void bdd_printdot(BDD r)
{
bdd_fprintdot(stdout, r);
}
int bdd_fnprintdot(char *fname, BDD r)
{
FILE *ofile = fopen(fname, "w");
if (ofile == NULL)
return bdd_error(BDD_FILE);
bdd_fprintdot(ofile, r);
fclose(ofile);
return 0;
}
void bdd_fprintdot(FILE* ofile, BDD r)
{
fprintf(ofile, "digraph G {\n");
fprintf(ofile, "0 [shape=box, label=\"0\", style=filled, shape=box, height=0.3, width=0.3];\n");
fprintf(ofile, "1 [shape=box, label=\"1\", style=filled, shape=box, height=0.3, width=0.3];\n");
bdd_fprintdot_rec(ofile, r);
fprintf(ofile, "}\n");
bdd_unmark(r);
}
static void bdd_fprintdot_rec(FILE* ofile, BDD r)
{
if (ISCONST(r) || MARKED(r))
return;
fprintf(ofile, "%d [label=\"", r);
if (filehandler)
filehandler(ofile, bddlevel2var[LEVEL(r)]);
else
fprintf(ofile, "%d", bddlevel2var[LEVEL(r)]);
fprintf(ofile, "\"];\n");
fprintf(ofile, "%d -> %d [style=dotted];\n", r, LOW(r));
fprintf(ofile, "%d -> %d [style=filled];\n", r, HIGH(r));
SETMARK(r);
bdd_fprintdot_rec(ofile, LOW(r));
bdd_fprintdot_rec(ofile, HIGH(r));
}
/*=== SAVE =============================================================*/
/*
NAME {* bdd\_save *}
EXTRA {* bdd\_fnsave *}
SECTION {* fileio *}
SHORT {* saves a BDD to a file *}
PROTO {* int bdd_fnsave(char *fname, BDD r)
int bdd_save(FILE *ofile, BDD r) *}
DESCR {* Saves the nodes used by {\tt r} to either a file {\tt ofile}
which must be opened for writing or to the file named {\tt fname}.
In the last case the file will be truncated and opened for
writing. *}
ALSO {* bdd\_load *}
RETURN {* Zero on succes, otherwise an error code from {\tt bdd.h}. *}
*/
int bdd_fnsave(char *fname, BDD r)
{
FILE *ofile;
int ok;
if ((ofile=fopen(fname,"w")) == NULL)
return bdd_error(BDD_FILE);
ok = bdd_save(ofile, r);
fclose(ofile);
return ok;
}
int bdd_save(FILE *ofile, BDD r)
{
int err, n=0;
if (r < 2)
{
fprintf(ofile, "0 0 %d\n", r);
return 0;
}
bdd_markcount(r, &n);
bdd_unmark(r);
fprintf(ofile, "%d %d\n", n, bddvarnum);
for (n=0 ; n<bddvarnum ; n++)
fprintf(ofile, "%d ", bddvar2level[n]);
fprintf(ofile, "\n");
err = bdd_save_rec(ofile, r);
bdd_unmark(r);
return err;
}
static int bdd_save_rec(FILE *ofile, int root)
{
BddNode *node = &bddnodes[root];
int err;
if (root < 2)
return 0;
if (LEVELp(node) & MARKON)
return 0;
LEVELp(node) |= MARKON;
if ((err=bdd_save_rec(ofile, LOWp(node))) < 0)
return err;
if ((err=bdd_save_rec(ofile, HIGHp(node))) < 0)
return err;
fprintf(ofile, "%d %d %d %d\n",
root, bddlevel2var[LEVELp(node) & MARKHIDE],
LOWp(node), HIGHp(node));
return 0;
}
/*=== LOAD =============================================================*/
/*
NAME {* bdd\_load *}
EXTRA {* bdd\_fnload *}
SECTION {* fileio *}
SHORT {* loads a BDD from a file *}
PROTO {* int bdd_fnload(char *fname, BDD *r)
int bdd_load(FILE *ifile, BDD *r) *}
DESCR {* Loads a BDD from a file into the BDD pointed to by {\tt r}.
The file can either be the file {\tt ifile} which must be opened
for reading or the file named {\tt fname} which will be opened
automatically for reading.
The input file format consists of integers arranged in the following
manner. First the number of nodes $N$ used by the BDD and then the
number of variables $V$ allocated and the variable ordering
in use at the time the BDD was saved.
If $N$ and $V$ are both zero then the BDD is either the constant
true or false BDD, indicated by a $1$ or a $0$ as the next integer.
In any other case the next $N$ sets of $4$ integers will describe
the nodes used by the BDD. Each set consists of first the node
number, then the variable number and then the low and high nodes.
The nodes {\it must} be saved in a order such that any low or
high node must be defined before it is mentioned. *}
ALSO {* bdd\_save *}
RETURN {* Zero on succes, otherwise an error code from {\tt bdd.h}. *}
*/
int bdd_fnload(char *fname, BDD *root)
{
FILE *ifile;
int ok;
if ((ifile=fopen(fname,"r")) == NULL)
return bdd_error(BDD_FILE);
ok = bdd_load(ifile, root);
fclose(ifile);
return ok;
}
int bdd_load(FILE *ifile, BDD *root)
{
int n, vnum, tmproot;
if (fscanf(ifile, "%d %d", &lh_nodenum, &vnum) != 2)
return bdd_error(BDD_FORMAT);
/* Check for constant true / false */
if (lh_nodenum==0 && vnum==0)
{
fscanf(ifile, "%d", root);
return 0;
}
if ((loadvar2level=(int*)malloc(sizeof(int)*vnum)) == NULL)
return bdd_error(BDD_MEMORY);
for (n=0 ; n<vnum ; n++)
fscanf(ifile, "%d", &loadvar2level[n]);
if (vnum > bddvarnum)
bdd_setvarnum(vnum);
if ((lh_table=(LoadHash*)malloc(lh_nodenum*sizeof(LoadHash))) == NULL)
return bdd_error(BDD_MEMORY);
for (n=0 ; n<lh_nodenum ; n++)
{
lh_table[n].first = -1;
lh_table[n].next = n+1;
}
lh_table[lh_nodenum-1].next = -1;
lh_freepos = 0;
tmproot = bdd_loaddata(ifile);
for (n=0 ; n<lh_nodenum ; n++)
bdd_delref(lh_table[n].data);
free(lh_table);
free(loadvar2level);
*root = 0;
if (tmproot < 0)
return tmproot;
else
*root = tmproot;
return 0;
}
static int bdd_loaddata(FILE *ifile)
{
int key,var,low,high,root=0,n;
for (n=0 ; n<lh_nodenum ; n++)
{
if (fscanf(ifile,"%d %d %d %d", &key, &var, &low, &high) != 4)
return bdd_error(BDD_FORMAT);
if (low >= 2)
low = loadhash_get(low);
if (high >= 2)
high = loadhash_get(high);
if (low<0 || high<0 || var<0)
return bdd_error(BDD_FORMAT);
root = bdd_addref( bdd_ite(bdd_ithvar(var), high, low) );
loadhash_add(key, root);
}
return root;
}
static void loadhash_add(int key, int data)
{
int hash = key % lh_nodenum;
int pos = lh_freepos;
lh_freepos = lh_table[pos].next;
lh_table[pos].next = lh_table[hash].first;
lh_table[hash].first = pos;
lh_table[pos].key = key;
lh_table[pos].data = data;
}
static int loadhash_get(int key)
{
int hash = lh_table[key % lh_nodenum].first;
while (hash != -1 && lh_table[hash].key != key)
hash = lh_table[hash].next;
if (hash == -1)
return -1;
return lh_table[hash].data;
}
/* EOF */