/*======================================================================== 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: /cvsroot/buddy/buddy/src/bddio.c,v 1.1.1.1 2004/06/25 13:22:14 haimcohen Exp $ FILE: bddio.c DESCR: File I/O routines for BDD package AUTH: Jorn Lind DATE: (C) june 1997 *************************************************************************/ #include #include #include #include #include #include "gecode/support/buddy/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\\ < $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 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, height=0.3, width=0.3];\n"); fprintf(ofile, "1 [shape=box, label=\"1\", style=filled, height=0.3, width=0.3];\n"); fprintf(ofile, "node[shape=circle];\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) bdd_setvarnum(vnum); if ((lh_table=(LoadHash*)malloc(lh_nodenum*sizeof(LoadHash))) == NULL) return bdd_error(BDD_MEMORY); for (n=0 ; n= 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 */ // STATISTICS: buddy-any