APM: RSMC version 1.0 (not 1.0a) from ipisvn

This commit is contained in:
Artur Meski
2017-11-18 20:30:18 +00:00
parent 27c43717fa
commit 69a9825c8b
2071 changed files with 222512 additions and 0 deletions

41
Makefile Normal file
View File

@@ -0,0 +1,41 @@
CC = g++
CUDD_PATH = cudd
CUDD_INCLUDE = $(CUDD_PATH)/obj/cuddObj.o $(CUDD_PATH)/cudd/libcudd.a $(CUDD_PATH)/mtr/libmtr.a \
$(CUDD_PATH)/st/libst.a $(CUDD_PATH)/util/libutil.a \
$(CUDD_PATH)/epd/libepd.a $(CUDD_PATH)/obj/libobj.a
INCLUDES=-Icudd/include
CPPFLAGS = -Wall $(INCLUDES) #-Werror
#CPPFLAGS = -Wall -DNDEBUG
CXXFLAGS = -std=c++14 -O3 -DPUBLIC_RELEASE -DNDEBUG #-g
LDLIBS = $(CUDD_INCLUDE) #-lcuddobj #/lib64/libcudd.so.2 #$(CUDD_INCLUDE)
OBJ = rs.o symrs.o mc.o rsin_driver.o rsin_parser.o rsin_parser.lex.o formrsctl.o
all: main
cleanly:
rm -f *.lex.cc *.lex.o location.hh stack.hh position.hh rsin_parser.cc rsin_parser.hh
clean: cleanly
rm -f *.o main *~ makefile.dep tags
cleanall: clean
makefile.dep: *.cc *.hh
for i in *.cc; do g++ $(INCLUDES) -MM -MG "$${i}"; done > $@
include makefile.dep
main: main.o $(OBJ)
rsin_parser.hh: rsin_parser.cc
rsin_parser.cc: rsin_parser.yy
bison -o rsin_parser.cc rsin_parser.yy
rsin_parser.o: rsin_parser.cc
rsin_parser.lex.cc: rsin_parser.ll
flex rsin_parser.ll
mv lex.yy.c rsin_parser.lex.cc

8
bdd_macro.hh Normal file
View File

@@ -0,0 +1,8 @@
#ifndef __BDD_MACRO_HH__
#define __BDD_MACRO_HH__
#define BDD_IFF(p,q) (!(p+q)+(p*q))
#define BDD_TRUE (cuddMgr->bddOne())
#define BDD_FALSE (cuddMgr->bddZero())
#endif

1
cudd.hh Normal file
View File

@@ -0,0 +1 @@
#include <cudd/cuddObj.hh>

31
cudd_local/LICENSE Normal file
View File

@@ -0,0 +1,31 @@
Copyright (c) 1995-2004, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

318
cudd_local/Makefile Normal file
View File

@@ -0,0 +1,318 @@
# $Id$
#
# Makefile for the CUDD distribution kit
#---------------------------------------------------------------------------
# Beginning of the configuration section. These symbol definitions can
# be overridden from the command line.
# C++ compiler
CXX = g++
#CXX = icpc
#CXX = ecpc
#CXX = CC
#CXX = /usr/local/opt/SUNWspro/bin/CC
#CXX = cxx
# Specific options for compilation of C++ files.
CXXFLAGS =
# Stricter standard conformance for g++.
#CXXFLAGS = -std=c++98
# For Sun CC version 5, this invokes compatibility mode.
#CXXFLAGS = -compat
# On some versions of UP-UX, it is necessary to pass the option +a1
# to CC for the C++ test program to compile successfully.
#CXXFLAGS = +a1
# C compiler used for all targets except optimize_dec, which always uses cc.
#CC = cc
#CC = /usr/local/opt/SUNWspro/bin/cc
CC = gcc
#CC = icc
#CC = ecc
#CC = /usr/ucb/cc
#CC = c89
#CC = $(CXX)
# On some machines ranlib is either non-existent or redundant.
# Use the following definition if your machine has ranlib and you think
# it is needed.
RANLIB = ranlib
# Use the following definition if your machine either does not have
# ranlib (e.g., SUN running solaris) or can do without it (e.g., DEC Alpha).
#RANLIB = :
# Use ICFLAGS to specify machine-independent compilation flags.
# These three are typical settings for cc.
#ICFLAGS = -g
#ICFLAGS = -O
#ICFLAGS =
# These two are typical settings for optimized code with gcc.
#ICFLAGS = -g -O3 -Wall
ICFLAGS = -g -O3
# Use XCFLAGS to specify machine-dependent compilation flags.
# For some platforms no special flags are needed.
#XCFLAGS = -DHAVE_IEEE_754 -DBSD
#
#==========================
# Linux
#
# Gcc 4.2.4 or higher on i686.
#XCFLAGS = -DHAVE_IEEE_754 -DBSD
# Gcc 3.2.2 or higher on i686.
#XCFLAGS = -mtune=pentium4 -malign-double -DHAVE_IEEE_754 -DBSD
# Gcc 2.8.1 on i686.
#XCFLAGS = -mcpu=pentiumpro -malign-double -DHAVE_IEEE_754 -DBSD
# Gcc 4.2.4 or higher on x86_64 (64-bit compilation)
XCFLAGS = -mtune=native -DHAVE_IEEE_754 -DBSD -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8
# Gcc 4.2.4 or higher on x86_64 (32-bit compilation)
#XCFLAGS = -m32 -mtune=native -malign-double -DHAVE_IEEE_754 -DBSD
# Icc on i686 (older versions may not support -xHost).
#XCFLAGS = -ansi -xHost -align -ip -DHAVE_IEEE_754 -DBSD
# Icc on x86_64 (64-bit compilation).
#XCFLAGS = -ansi -xHost -align -ip -DHAVE_IEEE_754 -DBSD -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8
# Gcc on ia64.
#XCFLAGS = -DHAVE_IEEE_754 -DBSD -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8
# Icc/ecc on ia64.
#XCFLAGS = -ansi -DBSD -DHAVE_IEEE_754 -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8
#
#==========================
# Solaris
#
# For Solaris, BSD should not be replaced by UNIX100.
#XCFLAGS = -DHAVE_IEEE_754 -DUNIX100 -DEPD_BIG_ENDIAN
# Gcc 2.8.1 or higher on Ultrasparc.
#XCFLAGS = -mcpu=ultrasparc -DHAVE_IEEE_754 -DUNIX100 -DEPD_BIG_ENDIAN
# For Solaris 2.5 and higher, optimized code with /usr/bin/cc or CC.
#XCFLAGS = -DHAVE_IEEE_754 -DUNIX100 -xO5 -native -dalign -DEPD_BIG_ENDIAN
# On IA platforms, -dalign is not supported and causes warnings.
#XCFLAGS = -DHAVE_IEEE_754 -DUNIX100 -xO5 -native
# Recent Sun compilers won't let you use -native on old Ultras.
#XCFLAGS = -DHAVE_IEEE_754 -DUNIX100 -xO5 -dalign -xlibmil -DEPD_BIG_ENDIAN
# For Solaris 2.4, optimized code with /usr/bin/cc.
#XCFLAGS = -DHAVE_IEEE_754 -DUNIX100 -xO4 -dalign -DEPD_BIG_ENDIAN
# For Solaris 2.5 and higher, optimized code with /usr/ucb/cc.
#XCFLAGS = -DHAVE_IEEE_754 -DBSD -xO5 -native -dalign -DEPD_BIG_ENDIAN
#XCFLAGS = -DHAVE_IEEE_754 -DBSD -xO5 -dalign -xlibmil -DEPD_BIG_ENDIAN
# For Solaris 2.4, optimized code with /usr/ucb/cc.
#XCFLAGS = -DHAVE_IEEE_754 -DBSD -xO4 -dalign -DEPD_BIG_ENDIAN
#
#==========================
# DEC Alphas running Digital Unix
#
# For DEC Alphas either -ieee_with_inexact or -ieee_with_no_inexact is
# needed. If you use only BDDs, -ieee_with_no_inexact is enough.
# In the following, we consider three different compilers:
# - the old native compiler (the one of MIPS ancestry that produces u-code);
# - the new native compiler;
# - gcc
# On the Alphas, gcc (as of release 2.7.2) does not support 32-bit pointers
# and IEEE 754 floating point arithmetic. Therefore, for this architecture
# only, the native compilers provide a substatial advantage.
# With the native compilers, specify -xtaso for 32-bit pointers.
# Do not use -xtaso_short because explicit reference to stdout and stderr
# does not work with this option. (Among other things.)
# Notice that -taso must be included in LDFLAGS for -xtaso to work.
# Given the number of possible choices, only some typical configurations
# are proposed here.
#
# Old native compiler for the Alphas; 64-bit pointers.
#XCFLAGS = -DBSD -DHAVE_IEEE_754 -ieee_with_no_inexact -tune host -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8
# Old native compiler for the Alphas; 32-bit pointers.
#XCFLAGS = -DBSD -DHAVE_IEEE_754 -ieee_with_no_inexact -tune host -xtaso -DSIZEOF_LONG=8
# New native compiler for the Alphas; 64-bit pointers.
#XCFLAGS = -g3 -O4 -std -DBSD -DHAVE_IEEE_754 -ieee_with_no_inexact -tune host -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8
# New native compiler for the Alphas; 32-bit pointers.
#XCFLAGS = -g3 -O4 -std -DBSD -DHAVE_IEEE_754 -ieee_with_no_inexact -tune host -xtaso -DSIZEOF_LONG=8
# gcc for the Alphas: compile without HAVE_IEEE_754.
#XCFLAGS = -DBSD -DSIZEOF_VOID_P=8 -DSIZEOF_LONG=8
#
#==========================
#
# IBM RS6000
#
# For the IBM RS6000 -qstrict is necessary when specifying -O3 with cc.
#XCFLAGS = -DBSD -DHAVE_IEEE_754 -DEPD_BIG_ENDIAN -O3 -qstrict
#
#==========================
#
# HP-UX
#
# I haven't figured out how to enable IEEE 754 on the HPs I've tried...
# For HP-UX using gcc.
#XCFLAGS = -DUNIX100 -DEPD_BIG_ENDIAN
# For HP-UX using c89.
#XCFLAGS = +O3 -DUNIX100 -DEPD_BIG_ENDIAN
#
#==========================
#
# Windows 95/98/NT/XP/Vista/7 with Cygwin tools
#
# The value of RLIMIT_DATA_DEFAULT should reflect the amount of
# available memory (expressed in bytes).
# Recent versions of cygwin have getrlimit, but the datasize limit
# cannot be set.
#XCFLAGS = -mtune=native -malign-double -DHAVE_IEEE_754 -DHAVE_GETRLIMIT=0 -DRLIMIT_DATA_DEFAULT=268435456
# Define the level of self-checking and verbosity of the CUDD package.
#DDDEBUG = -DDD_DEBUG -DDD_VERBOSE -DDD_STATS -DDD_CACHE_PROFILE -DDD_UNIQUE_PROFILE -DDD_COUNT
DDDEBUG =
# Define the level of self-checking and verbosity of the MTR package.
#MTRDEBUG = -DMTR_DEBUG
MTRDEBUG =
# Loader options.
LDFLAGS =
# This may produce faster code on the DECstations.
#LDFLAGS = -jmpopt -Olimit 1000
# This may be necessary under some old versions of Linux.
#LDFLAGS = -static
# This normally makes the program faster on the DEC Alphas.
#LDFLAGS = -non_shared -om
# This is for 32-bit pointers on the DEC Alphas.
#LDFLAGS = -non_shared -om -taso
#LDFLAGS = -non_shared -taso
# Define PURE as purify to link with purify.
# Define PURE as quantify to link with quantify.
# Remember to compile with -g if you want line-by-line info with quantify.
PURE =
#PURE = purify
#PURE = quantify
# Define EXE as .exe for MS-DOS and derivatives. Not required by recent
# versions of cygwin.
EXE =
#EXE = .exe
# End of the configuration section.
#---------------------------------------------------------------------------
MFLAG = -DMNEMOSYNE
MNEMLIB = ../mnemosyne/libmnem.a
DDWDIR = .
IDIR = $(DDWDIR)/include
INCLUDE = -I$(IDIR)
BDIRS = cudd dddmp mtr st util epd
DIRS = $(BDIRS)
#------------------------------------------------------------------------
.PHONY : build
.PHONY : check_leaks
.PHONY : optimize_dec
.PHONY : testcudd
.PHONY : libobj
.PHONY : testobj
.PHONY : testdddmp
.PHONY : testmtr
.PHONY : lint
.PHONY : all
.PHONY : clean
.PHONY : distclean
build:
sh ./setup.sh
@for dir in $(DIRS); do \
(cd $$dir; \
echo Making $$dir ...; \
make CC="$(CC)" RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" )\
done
check_leaks:
sh ./setup.sh
@for dir in $(DIRS); do \
(cd $$dir; \
echo Making $$dir ...; \
make CC="$(CC)" RANLIB=$(RANLIB) MFLAG=$(MFLAG) MNEMLIB=$(MNEMLIB) ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" EXE="$(EXE)" )\
done
optimize_dec:
sh ./setup.sh
@for dir in $(DIRS); do \
(cd $$dir; \
echo Making $$dir ...; \
make CC=$(CC) RANLIB=$(RANLIB) XCFLAGS="$(XCFLAGS)" LDFLAGS="$(LDFLAGS)" optimize_dec )\
done
lint:
sh ./setup.sh
@for dir in $(DIRS) obj; do \
(cd $$dir; \
echo Making lint in $$dir ...; \
make CC=$(CC) lint )\
done
tags:
sh ./setup.sh
@for dir in $(DIRS) obj; do \
(cd $$dir; \
echo Making tags in $$dir ...; \
make CC=$(CC) tags )\
done
all:
sh ./setup.sh
@for dir in $(DIRS); do \
(cd $$dir; \
echo Making all in $$dir ...; \
make CC=$(CC) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" all )\
done
testcudd:
sh ./setup.sh
@for dir in util st mtr epd; do \
(cd $$dir; \
echo Making $$dir ...; \
make CC=$(CC) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" )\
done
@(cd cudd; \
echo Making testcudd ...; \
make CC=$(CC) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" testcudd$(EXE) )
objlib:
sh ./setup.sh
@for dir in $(BDIRS); do \
(cd $$dir; \
echo Making $$dir ...; \
make CC=$(CC) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" )\
done
@(cd obj; \
echo Making obj ...; \
make CXX=$(CXX) CXXFLAGS=$(CXXFLAGS) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" )
testobj: objlib
@(cd obj; \
echo Making testobj ...; \
make CXX=$(CXX) CXXFLAGS=$(CXXFLAGS) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" testobj$(EXE) )
testdddmp: build
@(cd dddmp; \
echo Making testdddmp ...; \
make CC=$(CC) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" testdddmp$(EXE) )
testmtr: build
@(cd mtr; \
echo Making testmtr ...; \
make CC=$(CC) RANLIB=$(RANLIB) MFLAG= MNEMLIB= ICFLAGS="$(ICFLAGS)" XCFLAGS="$(XCFLAGS)" DDDEBUG="$(DDDEBUG)" MTRDEBUG="$(MTRDEBUG)" LDFLAGS="$(LDFLAGS)" PURE="$(PURE)" EXE="$(EXE)" testmtr$(EXE) )
clean:
@for dir in $(DIRS) obj; do \
(cd $$dir; \
echo Cleaning $$dir ...; \
make -s clean ) \
done
distclean:
@for dir in $(DIRS) obj; do \
(cd $$dir; \
echo Cleaning $$dir ...; \
make -s EXE="$(EXE)" distclean ) \
done
sh ./shutdown.sh

177
cudd_local/README Normal file
View File

@@ -0,0 +1,177 @@
$Id$
This directory contains a set of packages that allow you to build a toy
application based on the CUDD package.
The CUDD package is a package written in C for the manipulation of
decision diagrams. It supports binary decision diagrams (BDDs),
algebraic decision diagrams (ADDs), and Zero-Suppressed BDDs (ZDDs).
The toy application provided in this kit is called nanotrav and is a
simple-minded FSM traversal program. (See the README file and the man
page nanotrav.1 in the nanotrav directory for the details.) It is
included so that you can run a sanity check on your installation.
INSTALLATION
Before you build the libraries and programs, you need to check the
Makefile in the top directory. Go through the definitions contained in the
configuration section, and select the desired compiler and compilation
flags. Instructions are provided in the comments of the Makefile.
You can always specify the options on the command line. For instance,
on some machines you can build a "fast" version of the program by typing:
make DDDEBUG= MTRDEBUG= ICFLAGS=-O2
The Makefile supports several targets:
make:
Creates a "plain" version of the program.
make testdddmp:
Builds a test program (testdddmp) for BDD loading from and
storing to disk. See file README.test in the dddmp directory for
how to run the program.
make testobj:
Builds a test program for the C++ interface. Requires a C++
compiler. To run the program, run obj/testobj.
make testcudd:
Builds a test program for CUDD. To run the program, go to the
cudd directory and type "./testcudd -p 2 r7x8.1.mat". The result
can be compared to r7x7.1.out.
make testmtr:
Builds a test program for the mtr package. To run the program,
go to the mtr directory and type "./testmtr -p 1 test.groups".
make clean:
Cleans directories, but leaves libraries and programs.
make distclean:
Cleans thoroughly, returning the directories to their pristine
state.
The following targets are more or less obsolete and may disappear or
change in the future.
make check_leaks:
Creates a version of the program with the mnemosyne library
linked to it. It also builds the mnemalyse program, which
helps in finding memory leaks. This target does not work on the
IBM RS6000. The makefile also supports purify. To use purify,
set the PURE variable in the Makefile, and use the standard
target.
make optimize_dec:
Builds a version of the program using the u-code compiler
available on DEC machines (DECstations and Alphas). The newer
native compiler on the Alphas does not use u-code, though.
Therefore the standard target should be used with it.
make lint:
Runs lint on all subdirectories except mnemosyne. Creates lint
libraries for all object libraries.
make tags:
Builds ctags-style tag files for all subdirectories except
mnemosyne.
make all:
Makes all of the above, except check_leaks, which is
incompatible with a plain "make."
All targets, except clean and distclean, will create the include
directory if it does not already exist.
The Makefile does not compile the SIS interface (cuddBddPort.c and
cuddPwPt.c found in subdirectory sis). To compile the interface, you
also need array.h and var_set.h, which are not part of this
distribution, but come with SIS. Detailed instructions on how to
integrate the CUDD package in SIS can be found in the documentation
(cudd/doc).
PLATFORMS
This kit has been successfully built on the following configurations:
PC (ia32 and ia64) running Ubuntu with gcc
PC (ia32 and ia64) running Ubuntu with g++
PC (ia32 and ia64) running Linux RedHat with gcc
PC (ia32 and ia64) running Linux RedHat with g++
PC (ia64) running Cygwin on Windows 7 and Vista with gcc
PC (ia64) running Cygwin on Windows 7 and Vista with g++
Platforms to which I have no longer access and therefore are no longer
supported.
PC (ia32) running Linux RedHat with icc
PC (ia32) running Linux RedHat with icpc
PC (ia64) running Linux RedHat with ecc
PC (ia64) running Linux RedHat with ecpc
SUN running Solaris 2.8 with cc
SUN running Solaris 2.8 with CC
SUN running Solaris 2.8 with gcc
SUN running Solaris 2.8 with g++
DECstation running Ultrix with cc
DECstation running Ultrix with gcc
IBM RS6000 running AIX 3.2.4 with cc (**)
IBM RS6000 running AIX 3.2.4 with gcc
IBM RS6000 running AIX 3.2.4 with g++
SUN running SunOS with gcc
DEC Alpha running Digital Unix with cc
DEC Alpha running Digital Unix with cxx
DEC Alpha running Digital Unix with gcc
HP 9000/770 running HP-UX with c89
HP 9000/770 running HP-UX with CC
HP 9000/770 running HP-UX with gcc
HP 9000/770 running HP-UX with g++ (*)
SUN running Solaris 2.8 with /usr/ucb/cc
PC running Solaris 2.8 with /usr/bin/cc
PC running Solaris 2.8 with /usr/ucb/cc
PC running Solaris 2.8 with CC
PC running Solaris 2.8 with gcc
PC running Solaris 2.8 with g++
NOTES
(*) C programs were compiled with g++, but linked with gcc.
(**) Some old versions of the AIX cc compiler have buggy optimizers:
Try compiling with -O2 instead of -O3 if the program crashes.
Running lint and compiling with gcc -Wall still produces warnings.
Running `purify' under Solaris 2.8 generates no messages.
SANITY CHECK
The directory `nanotrav' contains a very simple application based on the
CUDD package. The `nanotrav' directory contains a man page that
describes the options nanotrav supports. The files *.blif are sample
input files for nanotrav.
If you have built the mnemosyne library (make check_leaks), you can do
cd mnemosyne
make runmtest
This does not work on machines running SunOS, but the version of
nanotrav that uses mnemosyne may work.
DOCUMENTATION
Directory cudd-2.5.0/cudd/doc contains HTML documentation for the CUDD
package. The recommended starting point is cuddIntro.html. Documentation
in both postscript(tm) format and plain text format is also provided.
Documentation for the auxiliary libraries (except for the util library)
is in the doc subdirectories.
FEEDBACK:
Send feedback to:
Fabio Somenzi
University of Colorado at Boulder
ECE Dept.
Boulder, CO 80309-0425
Fabio@Colorado.EDU
http://vlsi.colorado.edu/~fabio

131
cudd_local/RELEASE.NOTES Normal file
View File

@@ -0,0 +1,131 @@
Release 2.5.0 of Cudd introduces the ability to set timeouts. The
function that is interrupted returns NULL (which the application must
be prepared to handle,) but the BDDs are uncorrupted and the invoking
program can continue to use the manager.
In addition, reordering is now aware of timeouts, so that it gives up
when a timeout is approaching to give the invoking program a chance to
obtain some results.
The response time to the timeout is not immediate, though most of the time
it is well below one second. Checking for timeouts has a small overhead.
In experiments, less than 1% has been observed on average.
Creation of BDD managers with many variables (e.g., tens or hundreds
of thousands) is now much more efficient. Computing small supports of
BDDs when there are many variables is also much more efficient, but
this has been at the cost of separating the function for BDDs and ADDs
(Cudd_Support) from that for ZDDs (Cudd_zddSupport).
The C++ interface has undergone a major upgrade.
The handling of variable gruops in reordering has been much improved.
(Thanks to Arie Gurfinkel for a very detailed bug report!) A handful
of other bugs have been fixed as well.
New Functions:
unsigned long Cudd_ReadStartTime(DdManager *unique);
unsigned long Cudd_ReadElapsedTime(DdManager *unique);
void Cudd_SetStartTime(DdManager *unique, unsigned long st);
void Cudd_ResetStartTime(DdManager *unique);
unsigned long Cudd_ReadTimeLimit(DdManager *unique);
void Cudd_SetTimeLimit(DdManager *unique, unsigned long tl);
void Cudd_UpdateTimeLimit(DdManager * unique);
void Cudd_IncreaseTimeLimit(DdManager * unique, unsigned long increase);
void Cudd_UnsetTimeLimit(DdManager *unique);
int Cudd_TimeLimited(DdManager *unique);
unsigned int Cudd_ReadMaxReorderings (DdManager *dd);
void Cudd_SetMaxReorderings (DdManager *dd, unsigned int mr);
unsigned int Cudd_ReadOrderRandomization(DdManager * dd);
void Cudd_SetOrderRandomization(DdManager * dd, unsigned int factor);
int Cudd_PrintGroupedOrder(DdManager * dd, const char *str, void *data);
int Cudd_EnableOrderingMonitoring(DdManager *dd);
int Cudd_DisableOrderingMonitoring(DdManager *dd);
int Cudd_OrderingMonitoring(DdManager *dd);
DdNode * Cudd_bddExistAbstractLimit(DdManager * manager, DdNode * f, DdNode * cube, unsigned int limit);
DdNode * Cudd_bddIteLimit (DdManager *dd, DdNode *f, DdNode *g, DdNode *h, unsigned int limit);
DdNode * Cudd_bddOrLimit (DdManager *dd, DdNode *f, DdNode *g, unsigned int limit);
DdNode * Cudd_bddXnorLimit (DdManager *dd, DdNode *f, DdNode *g, unsigned int limit);
int Cudd_CheckCube (DdManager *dd, DdNode *g);
DdNode * Cudd_bddMaximallyExpand(DdManager *dd, DdNode *lb, DdNode *ub, DdNode *f);
DdNode * Cudd_bddLargestPrimeUnate(DdManager *dd , DdNode *f, DdNode *phaseBdd);
int Cudd_Reserve(DdManager *manager, int amount);
int Cudd_SupportIndices(DdManager * dd, DdNode * f, int **indices);
int Cudd_VectorSupportIndices(DdManager * dd, DdNode ** F, int n, int **indices);
DdNode * Cudd_zddSupport(DdManager * dd, DdNode * f);
Changed prototypes:
unsigned int Cudd_ReadReorderings (DdManager *dd);
----------------------------------------------------------------------
Release 2.4.2 of Cudd features several bug fixes. The most important
are those that prevented Cudd from making full use of up to 4 GB of
memory when using 32-bit pointers. A handful of bugs were discovered by
Coverity. (Thanks to Christian Stangier!)
This release can be compiled with either 64-bit pointers or 32-bit
pointers on x86_64 platforms if sizeof(long) = sizeof(void *) = 8 and
sizeof(int) = 4. This is known as the LP64 model. For 32-bit pointers,
one usually needs supplementary libraries. On Ubuntu and Debian Linux,
one needs g++-multilib, which can be installed with
"apt-get install g++-multilib."
Added functions
DdNode *Cudd_Inequality (DdManager * dd, int N, int c, DdNode ** x,
DdNode ** y);
DdNode * Cudd_Disequality (DdManager * dd, int N, int c, DdNode ** x,
DdNode ** y);
DdNode * Cudd_bddInterval (DdManager * dd, int N, DdNode ** x,
unsigned int lowerB, unsigned int upperB);
Changed prototypes:
int Cudd_DumpBlif (DdManager *dd, int n, DdNode **f, char
**inames, char **onames, char *mname, FILE *fp, int mv);
int Cudd_DumpBlifBody (DdManager *dd, int n, DdNode **f, char
**inames, char **onames, FILE *fp, int mv);
The additional parameter allows the caller to choose between plain blif
and blif-MV.
----------------------------------------------------------------------
Release 2.4.1 of Cudd features one major change with respect to previous
releases. The licensing terms are now explicitly stated.

124
cudd_local/cudd/Makefile Normal file
View File

@@ -0,0 +1,124 @@
# $Id$
#
# Cudd - DD package
#---------------------------
.SUFFIXES: .o .c .u
CC = gcc
RANLIB = ranlib
PURE =
# Define EXE as .exe for MS-DOS and derivatives.
EXE =
#EXE = .exe
MFLAG =
ICFLAGS = -g
XCFLAGS = -DDD_STATS
CFLAGS = $(ICFLAGS) $(MFLAG) $(XCFLAGS)
#DDDEBUG = -DDD_DEBUG -DDD_CACHE_PROFILE -DDD_VERBOSE -DDD_UNIQUE_PROFILE
DDDEBUG =
LINTFLAGS = -u -n -DDD_STATS -DDD_CACHE_PROFILE -DDD_VERBOSE -DDD_DEBUG -DDD_UNIQUE_PROFILE
# this is to create the lint library
LINTSWITCH = -o
WHERE = ..
INCLUDE = $(WHERE)/include
LIBS = ./libcudd.a $(WHERE)/mtr/libmtr.a \
$(WHERE)/st/libst.a $(WHERE)/util/libutil.a $(WHERE)/epd/libepd.a
MNEMLIB =
BLIBS = -kL. -klcudd -kL$(WHERE)/mtr -klmtr \
-kL$(WHERE)/st -klst -kL$(WHERE)/util -klutil -kL$(WHERE)/epd -klepd
LINTLIBS = ./llib-lcudd.ln $(WHERE)/mtr/llib-lmtr.ln \
$(WHERE)/st/llib-lst.ln $(WHERE)/util/llib-lutil.ln \
$(WHERE)/epd/llib-lepd.ln
LDFLAGS =
# files for the package
P = cudd
PSRC = cuddAPI.c cuddAddAbs.c cuddAddApply.c cuddAddFind.c cuddAddIte.c \
cuddAddInv.c cuddAddNeg.c cuddAddWalsh.c cuddAndAbs.c \
cuddAnneal.c cuddApa.c cuddApprox.c cuddBddAbs.c cuddBddCorr.c \
cuddBddIte.c cuddBridge.c cuddCache.c cuddCheck.c cuddClip.c \
cuddCof.c cuddCompose.c cuddDecomp.c cuddEssent.c \
cuddExact.c cuddExport.c cuddGenCof.c cuddGenetic.c \
cuddGroup.c cuddHarwell.c cuddInit.c cuddInteract.c \
cuddLCache.c cuddLevelQ.c \
cuddLinear.c cuddLiteral.c cuddMatMult.c cuddPriority.c \
cuddRead.c cuddRef.c cuddReorder.c cuddSat.c cuddSign.c \
cuddSolve.c cuddSplit.c cuddSubsetHB.c cuddSubsetSP.c cuddSymmetry.c \
cuddTable.c cuddUtil.c cuddWindow.c cuddZddCount.c cuddZddFuncs.c \
cuddZddGroup.c cuddZddIsop.c cuddZddLin.c cuddZddMisc.c \
cuddZddPort.c cuddZddReord.c cuddZddSetop.c cuddZddSymm.c \
cuddZddUtil.c
PHDR = cudd.h cuddInt.h
POBJ = $(PSRC:.c=.o)
PUBJ = $(PSRC:.c=.u)
TARGET = test$(P)$(EXE)
TARGETu = test$(P)-u
# files for the test program
SRC = test$(P).c
OBJ = $(SRC:.c=.o)
UBJ = $(SRC:.c=.u)
#------------------------------------------------------
lib$(P).a: $(POBJ)
ar rv $@ $?
$(RANLIB) $@
.c.o: $(PSRC) $(PHDR)
$(CC) -c $< -I$(INCLUDE) $(CFLAGS) $(DDDEBUG)
optimize_dec: lib$(P).b
lib$(P).b: $(PUBJ)
ar rv $@ $?
$(RANLIB) $@
.c.u: $(PSRC) $(PHDR)
cc -j $< -I$(INCLUDE) $(XCFLAGS)
# if the header files change, recompile
$(POBJ): $(PHDR)
$(PUBJ): $(PHDR)
$(OBJ): $(PHDR)
$(UBJ): $(PHDR)
$(TARGET): $(SRC) $(OBJ) $(HDR) $(LIBS) $(MNEMLIB)
$(PURE) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(MNEMLIB) -lm
# optimize (DECstations and Alphas only: uses u-code)
$(TARGETu): $(SRC) $(UBJ) $(HDR) $(LIBS:.a=.b)
$(CC) -O3 -Olimit 1000 $(XCFLAGS) $(LDFLAGS) -o $@ $(UBJ) $(BLIBS) -lm
lint: llib-l$(P).ln
llib-l$(P).ln: $(PSRC) $(PHDR)
lint $(LINTFLAGS) $(LINTSWITCH)$(P) -I$(INCLUDE) $(PSRC)
lintpgm: lint
lint $(LINTFLAGS) -I$(INCLUDE) $(SRC) $(LINTLIBS)
tags: $(PSRC) $(PHDR)
ctags $(PSRC) $(PHDR)
all: lib$(P).a lib$(P).b llib-l$(P).ln tags
programs: $(TARGET) $(TARGETu) lintpgm
clean:
rm -f *.o *.u mon.out gmon.out *.pixie *.Addrs *.Counts mnem.* \
.pure core *.warnings
distclean: clean
rm -f $(TARGET) $(TARGETu) lib*.a lib$(P).b llib-l$(P).ln \
*.bak *~ tags .gdb_history *.qv *.qx

1070
cudd_local/cudd/cudd.h Normal file

File diff suppressed because it is too large Load Diff

4893
cudd_local/cudd/cuddAPI.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,579 @@
/**CFile***********************************************************************
FileName [cuddAddAbs.c]
PackageName [cudd]
Synopsis [Quantification functions for ADDs.]
Description [External procedures included in this module:
<ul>
<li> Cudd_addExistAbstract()
<li> Cudd_addUnivAbstract()
<li> Cudd_addOrAbstract()
</ul>
Internal procedures included in this module:
<ul>
<li> cuddAddExistAbstractRecur()
<li> cuddAddUnivAbstractRecur()
<li> cuddAddOrAbstractRecur()
</ul>
Static procedures included in this module:
<ul>
<li> addCheckPositiveCube()
</ul>]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddAddAbs.c,v 1.16 2012/02/05 01:07:18 fabio Exp $";
#endif
static DdNode *two;
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static int addCheckPositiveCube (DdManager *manager, DdNode *cube);
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Existentially Abstracts all the variables in cube from f.]
Description [Abstracts all the variables in cube from f by summing
over all possible values taken by the variables. Returns the
abstracted ADD.]
SideEffects [None]
SeeAlso [Cudd_addUnivAbstract Cudd_bddExistAbstract
Cudd_addOrAbstract]
******************************************************************************/
DdNode *
Cudd_addExistAbstract(
DdManager * manager,
DdNode * f,
DdNode * cube)
{
DdNode *res;
two = cuddUniqueConst(manager,(CUDD_VALUE_TYPE) 2);
if (two == NULL) return(NULL);
cuddRef(two);
if (addCheckPositiveCube(manager, cube) == 0) {
(void) fprintf(manager->err,"Error: Can only abstract cubes");
return(NULL);
}
do {
manager->reordered = 0;
res = cuddAddExistAbstractRecur(manager, f, cube);
} while (manager->reordered == 1);
if (res == NULL) {
Cudd_RecursiveDeref(manager,two);
return(NULL);
}
cuddRef(res);
Cudd_RecursiveDeref(manager,two);
cuddDeref(res);
return(res);
} /* end of Cudd_addExistAbstract */
/**Function********************************************************************
Synopsis [Universally Abstracts all the variables in cube from f.]
Description [Abstracts all the variables in cube from f by taking
the product over all possible values taken by the variable. Returns
the abstracted ADD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_addExistAbstract Cudd_bddUnivAbstract
Cudd_addOrAbstract]
******************************************************************************/
DdNode *
Cudd_addUnivAbstract(
DdManager * manager,
DdNode * f,
DdNode * cube)
{
DdNode *res;
if (addCheckPositiveCube(manager, cube) == 0) {
(void) fprintf(manager->err,"Error: Can only abstract cubes");
return(NULL);
}
do {
manager->reordered = 0;
res = cuddAddUnivAbstractRecur(manager, f, cube);
} while (manager->reordered == 1);
return(res);
} /* end of Cudd_addUnivAbstract */
/**Function********************************************************************
Synopsis [Disjunctively abstracts all the variables in cube from the
0-1 ADD f.]
Description [Abstracts all the variables in cube from the 0-1 ADD f
by taking the disjunction over all possible values taken by the
variables. Returns the abstracted ADD if successful; NULL
otherwise.]
SideEffects [None]
SeeAlso [Cudd_addUnivAbstract Cudd_addExistAbstract]
******************************************************************************/
DdNode *
Cudd_addOrAbstract(
DdManager * manager,
DdNode * f,
DdNode * cube)
{
DdNode *res;
if (addCheckPositiveCube(manager, cube) == 0) {
(void) fprintf(manager->err,"Error: Can only abstract cubes");
return(NULL);
}
do {
manager->reordered = 0;
res = cuddAddOrAbstractRecur(manager, f, cube);
} while (manager->reordered == 1);
return(res);
} /* end of Cudd_addOrAbstract */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_addExistAbstract.]
Description [Performs the recursive step of Cudd_addExistAbstract.
Returns the ADD obtained by abstracting the variables of cube from f,
if successful; NULL otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
DdNode *
cuddAddExistAbstractRecur(
DdManager * manager,
DdNode * f,
DdNode * cube)
{
DdNode *T, *E, *res, *res1, *res2, *zero;
statLine(manager);
zero = DD_ZERO(manager);
/* Cube is guaranteed to be a cube at this point. */
if (f == zero || cuddIsConstant(cube)) {
return(f);
}
/* Abstract a variable that does not appear in f => multiply by 2. */
if (cuddI(manager,f->index) > cuddI(manager,cube->index)) {
res1 = cuddAddExistAbstractRecur(manager, f, cuddT(cube));
if (res1 == NULL) return(NULL);
cuddRef(res1);
/* Use the "internal" procedure to be alerted in case of
** dynamic reordering. If dynamic reordering occurs, we
** have to abort the entire abstraction.
*/
res = cuddAddApplyRecur(manager,Cudd_addTimes,res1,two);
if (res == NULL) {
Cudd_RecursiveDeref(manager,res1);
return(NULL);
}
cuddRef(res);
Cudd_RecursiveDeref(manager,res1);
cuddDeref(res);
return(res);
}
if ((res = cuddCacheLookup2(manager, Cudd_addExistAbstract, f, cube)) != NULL) {
return(res);
}
T = cuddT(f);
E = cuddE(f);
/* If the two indices are the same, so are their levels. */
if (f->index == cube->index) {
res1 = cuddAddExistAbstractRecur(manager, T, cuddT(cube));
if (res1 == NULL) return(NULL);
cuddRef(res1);
res2 = cuddAddExistAbstractRecur(manager, E, cuddT(cube));
if (res2 == NULL) {
Cudd_RecursiveDeref(manager,res1);
return(NULL);
}
cuddRef(res2);
res = cuddAddApplyRecur(manager, Cudd_addPlus, res1, res2);
if (res == NULL) {
Cudd_RecursiveDeref(manager,res1);
Cudd_RecursiveDeref(manager,res2);
return(NULL);
}
cuddRef(res);
Cudd_RecursiveDeref(manager,res1);
Cudd_RecursiveDeref(manager,res2);
cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res);
cuddDeref(res);
return(res);
} else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
res1 = cuddAddExistAbstractRecur(manager, T, cube);
if (res1 == NULL) return(NULL);
cuddRef(res1);
res2 = cuddAddExistAbstractRecur(manager, E, cube);
if (res2 == NULL) {
Cudd_RecursiveDeref(manager,res1);
return(NULL);
}
cuddRef(res2);
res = (res1 == res2) ? res1 :
cuddUniqueInter(manager, (int) f->index, res1, res2);
if (res == NULL) {
Cudd_RecursiveDeref(manager,res1);
Cudd_RecursiveDeref(manager,res2);
return(NULL);
}
cuddDeref(res1);
cuddDeref(res2);
cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res);
return(res);
}
} /* end of cuddAddExistAbstractRecur */
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_addUnivAbstract.]
Description [Performs the recursive step of Cudd_addUnivAbstract.
Returns the ADD obtained by abstracting the variables of cube from f,
if successful; NULL otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
DdNode *
cuddAddUnivAbstractRecur(
DdManager * manager,
DdNode * f,
DdNode * cube)
{
DdNode *T, *E, *res, *res1, *res2, *one, *zero;
statLine(manager);
one = DD_ONE(manager);
zero = DD_ZERO(manager);
/* Cube is guaranteed to be a cube at this point.
** zero and one are the only constatnts c such that c*c=c.
*/
if (f == zero || f == one || cube == one) {
return(f);
}
/* Abstract a variable that does not appear in f. */
if (cuddI(manager,f->index) > cuddI(manager,cube->index)) {
res1 = cuddAddUnivAbstractRecur(manager, f, cuddT(cube));
if (res1 == NULL) return(NULL);
cuddRef(res1);
/* Use the "internal" procedure to be alerted in case of
** dynamic reordering. If dynamic reordering occurs, we
** have to abort the entire abstraction.
*/
res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res1);
if (res == NULL) {
Cudd_RecursiveDeref(manager,res1);
return(NULL);
}
cuddRef(res);
Cudd_RecursiveDeref(manager,res1);
cuddDeref(res);
return(res);
}
if ((res = cuddCacheLookup2(manager, Cudd_addUnivAbstract, f, cube)) != NULL) {
return(res);
}
T = cuddT(f);
E = cuddE(f);
/* If the two indices are the same, so are their levels. */
if (f->index == cube->index) {
res1 = cuddAddUnivAbstractRecur(manager, T, cuddT(cube));
if (res1 == NULL) return(NULL);
cuddRef(res1);
res2 = cuddAddUnivAbstractRecur(manager, E, cuddT(cube));
if (res2 == NULL) {
Cudd_RecursiveDeref(manager,res1);
return(NULL);
}
cuddRef(res2);
res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res2);
if (res == NULL) {
Cudd_RecursiveDeref(manager,res1);
Cudd_RecursiveDeref(manager,res2);
return(NULL);
}
cuddRef(res);
Cudd_RecursiveDeref(manager,res1);
Cudd_RecursiveDeref(manager,res2);
cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res);
cuddDeref(res);
return(res);
} else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
res1 = cuddAddUnivAbstractRecur(manager, T, cube);
if (res1 == NULL) return(NULL);
cuddRef(res1);
res2 = cuddAddUnivAbstractRecur(manager, E, cube);
if (res2 == NULL) {
Cudd_RecursiveDeref(manager,res1);
return(NULL);
}
cuddRef(res2);
res = (res1 == res2) ? res1 :
cuddUniqueInter(manager, (int) f->index, res1, res2);
if (res == NULL) {
Cudd_RecursiveDeref(manager,res1);
Cudd_RecursiveDeref(manager,res2);
return(NULL);
}
cuddDeref(res1);
cuddDeref(res2);
cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res);
return(res);
}
} /* end of cuddAddUnivAbstractRecur */
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_addOrAbstract.]
Description [Performs the recursive step of Cudd_addOrAbstract.
Returns the ADD obtained by abstracting the variables of cube from f,
if successful; NULL otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
DdNode *
cuddAddOrAbstractRecur(
DdManager * manager,
DdNode * f,
DdNode * cube)
{
DdNode *T, *E, *res, *res1, *res2, *one;
statLine(manager);
one = DD_ONE(manager);
/* Cube is guaranteed to be a cube at this point. */
if (cuddIsConstant(f) || cube == one) {
return(f);
}
/* Abstract a variable that does not appear in f. */
if (cuddI(manager,f->index) > cuddI(manager,cube->index)) {
res = cuddAddOrAbstractRecur(manager, f, cuddT(cube));
return(res);
}
if ((res = cuddCacheLookup2(manager, Cudd_addOrAbstract, f, cube)) != NULL) {
return(res);
}
T = cuddT(f);
E = cuddE(f);
/* If the two indices are the same, so are their levels. */
if (f->index == cube->index) {
res1 = cuddAddOrAbstractRecur(manager, T, cuddT(cube));
if (res1 == NULL) return(NULL);
cuddRef(res1);
if (res1 != one) {
res2 = cuddAddOrAbstractRecur(manager, E, cuddT(cube));
if (res2 == NULL) {
Cudd_RecursiveDeref(manager,res1);
return(NULL);
}
cuddRef(res2);
res = cuddAddApplyRecur(manager, Cudd_addOr, res1, res2);
if (res == NULL) {
Cudd_RecursiveDeref(manager,res1);
Cudd_RecursiveDeref(manager,res2);
return(NULL);
}
cuddRef(res);
Cudd_RecursiveDeref(manager,res1);
Cudd_RecursiveDeref(manager,res2);
} else {
res = res1;
}
cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res);
cuddDeref(res);
return(res);
} else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
res1 = cuddAddOrAbstractRecur(manager, T, cube);
if (res1 == NULL) return(NULL);
cuddRef(res1);
res2 = cuddAddOrAbstractRecur(manager, E, cube);
if (res2 == NULL) {
Cudd_RecursiveDeref(manager,res1);
return(NULL);
}
cuddRef(res2);
res = (res1 == res2) ? res1 :
cuddUniqueInter(manager, (int) f->index, res1, res2);
if (res == NULL) {
Cudd_RecursiveDeref(manager,res1);
Cudd_RecursiveDeref(manager,res2);
return(NULL);
}
cuddDeref(res1);
cuddDeref(res2);
cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res);
return(res);
}
} /* end of cuddAddOrAbstractRecur */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Checks whether cube is an ADD representing the product
of positive literals.]
Description [Checks whether cube is an ADD representing the product of
positive literals. Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
addCheckPositiveCube(
DdManager * manager,
DdNode * cube)
{
if (Cudd_IsComplement(cube)) return(0);
if (cube == DD_ONE(manager)) return(1);
if (cuddIsConstant(cube)) return(0);
if (cuddE(cube) == DD_ZERO(manager)) {
return(addCheckPositiveCube(manager, cuddT(cube)));
}
return(0);
} /* end of addCheckPositiveCube */

View File

@@ -0,0 +1,941 @@
/**CFile***********************************************************************
FileName [cuddAddApply.c]
PackageName [cudd]
Synopsis [Apply functions for ADDs and their operators.]
Description [External procedures included in this module:
<ul>
<li> Cudd_addApply()
<li> Cudd_addMonadicApply()
<li> Cudd_addPlus()
<li> Cudd_addTimes()
<li> Cudd_addThreshold()
<li> Cudd_addSetNZ()
<li> Cudd_addDivide()
<li> Cudd_addMinus()
<li> Cudd_addMinimum()
<li> Cudd_addMaximum()
<li> Cudd_addOneZeroMaximum()
<li> Cudd_addDiff()
<li> Cudd_addAgreement()
<li> Cudd_addOr()
<li> Cudd_addNand()
<li> Cudd_addNor()
<li> Cudd_addXor()
<li> Cudd_addXnor()
</ul>
Internal procedures included in this module:
<ul>
<li> cuddAddApplyRecur()
<li> cuddAddMonadicApplyRecur()
</ul>]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddAddApply.c,v 1.19 2012/02/05 01:07:18 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Applies op to the corresponding discriminants of f and g.]
Description [Applies op to the corresponding discriminants of f and g.
Returns a pointer to the result if succssful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_addMonadicApply Cudd_addPlus Cudd_addTimes
Cudd_addThreshold Cudd_addSetNZ Cudd_addDivide Cudd_addMinus Cudd_addMinimum
Cudd_addMaximum Cudd_addOneZeroMaximum Cudd_addDiff Cudd_addAgreement
Cudd_addOr Cudd_addNand Cudd_addNor Cudd_addXor Cudd_addXnor]
******************************************************************************/
DdNode *
Cudd_addApply(
DdManager * dd,
DD_AOP op,
DdNode * f,
DdNode * g)
{
DdNode *res;
do {
dd->reordered = 0;
res = cuddAddApplyRecur(dd,op,f,g);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_addApply */
/**Function********************************************************************
Synopsis [Integer and floating point addition.]
Description [Integer and floating point addition. Returns NULL if not
a terminal case; f+g otherwise.]
SideEffects [None]
SeeAlso [Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addPlus(
DdManager * dd,
DdNode ** f,
DdNode ** g)
{
DdNode *res;
DdNode *F, *G;
CUDD_VALUE_TYPE value;
F = *f; G = *g;
if (F == DD_ZERO(dd)) return(G);
if (G == DD_ZERO(dd)) return(F);
if (cuddIsConstant(F) && cuddIsConstant(G)) {
value = cuddV(F)+cuddV(G);
res = cuddUniqueConst(dd,value);
return(res);
}
if (F > G) { /* swap f and g */
*f = G;
*g = F;
}
return(NULL);
} /* end of Cudd_addPlus */
/**Function********************************************************************
Synopsis [Integer and floating point multiplication.]
Description [Integer and floating point multiplication. Returns NULL
if not a terminal case; f * g otherwise. This function can be used also
to take the AND of two 0-1 ADDs.]
SideEffects [None]
SeeAlso [Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addTimes(
DdManager * dd,
DdNode ** f,
DdNode ** g)
{
DdNode *res;
DdNode *F, *G;
CUDD_VALUE_TYPE value;
F = *f; G = *g;
if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ZERO(dd));
if (F == DD_ONE(dd)) return(G);
if (G == DD_ONE(dd)) return(F);
if (cuddIsConstant(F) && cuddIsConstant(G)) {
value = cuddV(F)*cuddV(G);
res = cuddUniqueConst(dd,value);
return(res);
}
if (F > G) { /* swap f and g */
*f = G;
*g = F;
}
return(NULL);
} /* end of Cudd_addTimes */
/**Function********************************************************************
Synopsis [f if f&gt;=g; 0 if f&lt;g.]
Description [Threshold operator for Apply (f if f &gt;=g; 0 if f&lt;g).
Returns NULL if not a terminal case; f op g otherwise.]
SideEffects [None]
SeeAlso [Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addThreshold(
DdManager * dd,
DdNode ** f,
DdNode ** g)
{
DdNode *F, *G;
F = *f; G = *g;
if (F == G || F == DD_PLUS_INFINITY(dd)) return(F);
if (cuddIsConstant(F) && cuddIsConstant(G)) {
if (cuddV(F) >= cuddV(G)) {
return(F);
} else {
return(DD_ZERO(dd));
}
}
return(NULL);
} /* end of Cudd_addThreshold */
/**Function********************************************************************
Synopsis [This operator sets f to the value of g wherever g != 0.]
Description [This operator sets f to the value of g wherever g != 0.
Returns NULL if not a terminal case; f op g otherwise.]
SideEffects [None]
SeeAlso [Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addSetNZ(
DdManager * dd,
DdNode ** f,
DdNode ** g)
{
DdNode *F, *G;
F = *f; G = *g;
if (F == G) return(F);
if (F == DD_ZERO(dd)) return(G);
if (G == DD_ZERO(dd)) return(F);
if (cuddIsConstant(G)) return(G);
return(NULL);
} /* end of Cudd_addSetNZ */
/**Function********************************************************************
Synopsis [Integer and floating point division.]
Description [Integer and floating point division. Returns NULL if not
a terminal case; f / g otherwise.]
SideEffects [None]
SeeAlso [Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addDivide(
DdManager * dd,
DdNode ** f,
DdNode ** g)
{
DdNode *res;
DdNode *F, *G;
CUDD_VALUE_TYPE value;
F = *f; G = *g;
/* We would like to use F == G -> F/G == 1, but F and G may
** contain zeroes. */
if (F == DD_ZERO(dd)) return(DD_ZERO(dd));
if (G == DD_ONE(dd)) return(F);
if (cuddIsConstant(F) && cuddIsConstant(G)) {
value = cuddV(F)/cuddV(G);
res = cuddUniqueConst(dd,value);
return(res);
}
return(NULL);
} /* end of Cudd_addDivide */
/**Function********************************************************************
Synopsis [Integer and floating point subtraction.]
Description [Integer and floating point subtraction. Returns NULL if
not a terminal case; f - g otherwise.]
SideEffects [None]
SeeAlso [Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addMinus(
DdManager * dd,
DdNode ** f,
DdNode ** g)
{
DdNode *res;
DdNode *F, *G;
CUDD_VALUE_TYPE value;
F = *f; G = *g;
if (F == G) return(DD_ZERO(dd));
if (F == DD_ZERO(dd)) return(cuddAddNegateRecur(dd,G));
if (G == DD_ZERO(dd)) return(F);
if (cuddIsConstant(F) && cuddIsConstant(G)) {
value = cuddV(F)-cuddV(G);
res = cuddUniqueConst(dd,value);
return(res);
}
return(NULL);
} /* end of Cudd_addMinus */
/**Function********************************************************************
Synopsis [Integer and floating point min.]
Description [Integer and floating point min for Cudd_addApply.
Returns NULL if not a terminal case; min(f,g) otherwise.]
SideEffects [None]
SeeAlso [Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addMinimum(
DdManager * dd,
DdNode ** f,
DdNode ** g)
{
DdNode *F, *G;
F = *f; G = *g;
if (F == DD_PLUS_INFINITY(dd)) return(G);
if (G == DD_PLUS_INFINITY(dd)) return(F);
if (F == G) return(F);
#if 0
/* These special cases probably do not pay off. */
if (F == DD_MINUS_INFINITY(dd)) return(F);
if (G == DD_MINUS_INFINITY(dd)) return(G);
#endif
if (cuddIsConstant(F) && cuddIsConstant(G)) {
if (cuddV(F) <= cuddV(G)) {
return(F);
} else {
return(G);
}
}
if (F > G) { /* swap f and g */
*f = G;
*g = F;
}
return(NULL);
} /* end of Cudd_addMinimum */
/**Function********************************************************************
Synopsis [Integer and floating point max.]
Description [Integer and floating point max for Cudd_addApply.
Returns NULL if not a terminal case; max(f,g) otherwise.]
SideEffects [None]
SeeAlso [Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addMaximum(
DdManager * dd,
DdNode ** f,
DdNode ** g)
{
DdNode *F, *G;
F = *f; G = *g;
if (F == G) return(F);
if (F == DD_MINUS_INFINITY(dd)) return(G);
if (G == DD_MINUS_INFINITY(dd)) return(F);
#if 0
/* These special cases probably do not pay off. */
if (F == DD_PLUS_INFINITY(dd)) return(F);
if (G == DD_PLUS_INFINITY(dd)) return(G);
#endif
if (cuddIsConstant(F) && cuddIsConstant(G)) {
if (cuddV(F) >= cuddV(G)) {
return(F);
} else {
return(G);
}
}
if (F > G) { /* swap f and g */
*f = G;
*g = F;
}
return(NULL);
} /* end of Cudd_addMaximum */
/**Function********************************************************************
Synopsis [Returns 1 if f &gt; g and 0 otherwise.]
Description [Returns 1 if f &gt; g and 0 otherwise. Used in
conjunction with Cudd_addApply. Returns NULL if not a terminal
case.]
SideEffects [None]
SeeAlso [Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addOneZeroMaximum(
DdManager * dd,
DdNode ** f,
DdNode ** g)
{
if (*f == *g) return(DD_ZERO(dd));
if (*g == DD_PLUS_INFINITY(dd))
return DD_ZERO(dd);
if (cuddIsConstant(*f) && cuddIsConstant(*g)) {
if (cuddV(*f) > cuddV(*g)) {
return(DD_ONE(dd));
} else {
return(DD_ZERO(dd));
}
}
return(NULL);
} /* end of Cudd_addOneZeroMaximum */
/**Function********************************************************************
Synopsis [Returns plusinfinity if f=g; returns min(f,g) if f!=g.]
Description [Returns NULL if not a terminal case; f op g otherwise,
where f op g is plusinfinity if f=g; min(f,g) if f!=g.]
SideEffects [None]
SeeAlso [Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addDiff(
DdManager * dd,
DdNode ** f,
DdNode ** g)
{
DdNode *F, *G;
F = *f; G = *g;
if (F == G) return(DD_PLUS_INFINITY(dd));
if (F == DD_PLUS_INFINITY(dd)) return(G);
if (G == DD_PLUS_INFINITY(dd)) return(F);
if (cuddIsConstant(F) && cuddIsConstant(G)) {
if (cuddV(F) != cuddV(G)) {
if (cuddV(F) < cuddV(G)) {
return(F);
} else {
return(G);
}
} else {
return(DD_PLUS_INFINITY(dd));
}
}
return(NULL);
} /* end of Cudd_addDiff */
/**Function********************************************************************
Synopsis [f if f==g; background if f!=g.]
Description [Returns NULL if not a terminal case; f op g otherwise,
where f op g is f if f==g; background if f!=g.]
SideEffects [None]
SeeAlso [Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addAgreement(
DdManager * dd,
DdNode ** f,
DdNode ** g)
{
DdNode *F, *G;
F = *f; G = *g;
if (F == G) return(F);
if (F == dd->background) return(F);
if (G == dd->background) return(G);
if (cuddIsConstant(F) && cuddIsConstant(G)) return(dd->background);
return(NULL);
} /* end of Cudd_addAgreement */
/**Function********************************************************************
Synopsis [Disjunction of two 0-1 ADDs.]
Description [Disjunction of two 0-1 ADDs. Returns NULL
if not a terminal case; f OR g otherwise.]
SideEffects [None]
SeeAlso [Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addOr(
DdManager * dd,
DdNode ** f,
DdNode ** g)
{
DdNode *F, *G;
F = *f; G = *g;
if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ONE(dd));
if (cuddIsConstant(F)) return(G);
if (cuddIsConstant(G)) return(F);
if (F == G) return(F);
if (F > G) { /* swap f and g */
*f = G;
*g = F;
}
return(NULL);
} /* end of Cudd_addOr */
/**Function********************************************************************
Synopsis [NAND of two 0-1 ADDs.]
Description [NAND of two 0-1 ADDs. Returns NULL
if not a terminal case; f NAND g otherwise.]
SideEffects [None]
SeeAlso [Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addNand(
DdManager * dd,
DdNode ** f,
DdNode ** g)
{
DdNode *F, *G;
F = *f; G = *g;
if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ONE(dd));
if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
if (F > G) { /* swap f and g */
*f = G;
*g = F;
}
return(NULL);
} /* end of Cudd_addNand */
/**Function********************************************************************
Synopsis [NOR of two 0-1 ADDs.]
Description [NOR of two 0-1 ADDs. Returns NULL
if not a terminal case; f NOR g otherwise.]
SideEffects [None]
SeeAlso [Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addNor(
DdManager * dd,
DdNode ** f,
DdNode ** g)
{
DdNode *F, *G;
F = *f; G = *g;
if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ZERO(dd));
if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd));
if (F > G) { /* swap f and g */
*f = G;
*g = F;
}
return(NULL);
} /* end of Cudd_addNor */
/**Function********************************************************************
Synopsis [XOR of two 0-1 ADDs.]
Description [XOR of two 0-1 ADDs. Returns NULL
if not a terminal case; f XOR g otherwise.]
SideEffects [None]
SeeAlso [Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addXor(
DdManager * dd,
DdNode ** f,
DdNode ** g)
{
DdNode *F, *G;
F = *f; G = *g;
if (F == G) return(DD_ZERO(dd));
if (F == DD_ONE(dd) && G == DD_ZERO(dd)) return(DD_ONE(dd));
if (G == DD_ONE(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd));
if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
if (F > G) { /* swap f and g */
*f = G;
*g = F;
}
return(NULL);
} /* end of Cudd_addXor */
/**Function********************************************************************
Synopsis [XNOR of two 0-1 ADDs.]
Description [XNOR of two 0-1 ADDs. Returns NULL
if not a terminal case; f XNOR g otherwise.]
SideEffects [None]
SeeAlso [Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addXnor(
DdManager * dd,
DdNode ** f,
DdNode ** g)
{
DdNode *F, *G;
F = *f; G = *g;
if (F == G) return(DD_ONE(dd));
if (F == DD_ONE(dd) && G == DD_ONE(dd)) return(DD_ONE(dd));
if (G == DD_ZERO(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd));
if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
if (F > G) { /* swap f and g */
*f = G;
*g = F;
}
return(NULL);
} /* end of Cudd_addXnor */
/**Function********************************************************************
Synopsis [Applies op to the discriminants of f.]
Description [Applies op to the discriminants of f.
Returns a pointer to the result if succssful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_addApply Cudd_addLog]
******************************************************************************/
DdNode *
Cudd_addMonadicApply(
DdManager * dd,
DD_MAOP op,
DdNode * f)
{
DdNode *res;
do {
dd->reordered = 0;
res = cuddAddMonadicApplyRecur(dd,op,f);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_addMonadicApply */
/**Function********************************************************************
Synopsis [Natural logarithm of an ADD.]
Description [Natural logarithm of an ADDs. Returns NULL
if not a terminal case; log(f) otherwise. The discriminants of f must
be positive double's.]
SideEffects [None]
SeeAlso [Cudd_addMonadicApply]
******************************************************************************/
DdNode *
Cudd_addLog(
DdManager * dd,
DdNode * f)
{
if (cuddIsConstant(f)) {
CUDD_VALUE_TYPE value = log(cuddV(f));
DdNode *res = cuddUniqueConst(dd,value);
return(res);
}
return(NULL);
} /* end of Cudd_addLog */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_addApply.]
Description [Performs the recursive step of Cudd_addApply. Returns a
pointer to the result if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [cuddAddMonadicApplyRecur]
******************************************************************************/
DdNode *
cuddAddApplyRecur(
DdManager * dd,
DD_AOP op,
DdNode * f,
DdNode * g)
{
DdNode *res,
*fv, *fvn, *gv, *gvn,
*T, *E;
unsigned int ford, gord;
unsigned int index;
DD_CTFP cacheOp;
/* Check terminal cases. Op may swap f and g to increase the
* cache hit rate.
*/
statLine(dd);
res = (*op)(dd,&f,&g);
if (res != NULL) return(res);
/* Check cache. */
cacheOp = (DD_CTFP) op;
res = cuddCacheLookup2(dd,cacheOp,f,g);
if (res != NULL) return(res);
/* Recursive step. */
ford = cuddI(dd,f->index);
gord = cuddI(dd,g->index);
if (ford <= gord) {
index = f->index;
fv = cuddT(f);
fvn = cuddE(f);
} else {
index = g->index;
fv = fvn = f;
}
if (gord <= ford) {
gv = cuddT(g);
gvn = cuddE(g);
} else {
gv = gvn = g;
}
T = cuddAddApplyRecur(dd,op,fv,gv);
if (T == NULL) return(NULL);
cuddRef(T);
E = cuddAddApplyRecur(dd,op,fvn,gvn);
if (E == NULL) {
Cudd_RecursiveDeref(dd,T);
return(NULL);
}
cuddRef(E);
res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
if (res == NULL) {
Cudd_RecursiveDeref(dd, T);
Cudd_RecursiveDeref(dd, E);
return(NULL);
}
cuddDeref(T);
cuddDeref(E);
/* Store result. */
cuddCacheInsert2(dd,cacheOp,f,g,res);
return(res);
} /* end of cuddAddApplyRecur */
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_addMonadicApply.]
Description [Performs the recursive step of Cudd_addMonadicApply. Returns a
pointer to the result if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [cuddAddApplyRecur]
******************************************************************************/
DdNode *
cuddAddMonadicApplyRecur(
DdManager * dd,
DD_MAOP op,
DdNode * f)
{
DdNode *res, *ft, *fe, *T, *E;
unsigned int index;
/* Check terminal cases. */
statLine(dd);
res = (*op)(dd,f);
if (res != NULL) return(res);
/* Check cache. */
res = cuddCacheLookup1(dd,op,f);
if (res != NULL) return(res);
/* Recursive step. */
index = f->index;
ft = cuddT(f);
fe = cuddE(f);
T = cuddAddMonadicApplyRecur(dd,op,ft);
if (T == NULL) return(NULL);
cuddRef(T);
E = cuddAddMonadicApplyRecur(dd,op,fe);
if (E == NULL) {
Cudd_RecursiveDeref(dd,T);
return(NULL);
}
cuddRef(E);
res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
if (res == NULL) {
Cudd_RecursiveDeref(dd, T);
Cudd_RecursiveDeref(dd, E);
return(NULL);
}
cuddDeref(T);
cuddDeref(E);
/* Store result. */
cuddCacheInsert1(dd,op,f,res);
return(res);
} /* end of cuddAddMonadicApplyRecur */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/

View File

@@ -0,0 +1,316 @@
/**CFile***********************************************************************
FileName [cuddAddFind.c]
PackageName [cudd]
Synopsis [Functions to find maximum and minimum in an ADD and to
extract the i-th bit.]
Description [External procedures included in this module:
<ul>
<li> Cudd_addFindMax()
<li> Cudd_addFindMin()
<li> Cudd_addIthBit()
</ul>
Static functions included in this module:
<ul>
<li> addDoIthBit()
</ul>]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddAddFind.c,v 1.9 2012/02/05 01:07:18 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static DdNode * addDoIthBit (DdManager *dd, DdNode *f, DdNode *index);
/**AutomaticEnd***************************************************************/
#ifdef __cplusplus
}
#endif
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Finds the maximum discriminant of f.]
Description [Returns a pointer to a constant ADD.]
SideEffects [None]
******************************************************************************/
DdNode *
Cudd_addFindMax(
DdManager * dd,
DdNode * f)
{
DdNode *t, *e, *res;
statLine(dd);
if (cuddIsConstant(f)) {
return(f);
}
res = cuddCacheLookup1(dd,Cudd_addFindMax,f);
if (res != NULL) {
return(res);
}
t = Cudd_addFindMax(dd,cuddT(f));
if (t == DD_PLUS_INFINITY(dd)) return(t);
e = Cudd_addFindMax(dd,cuddE(f));
res = (cuddV(t) >= cuddV(e)) ? t : e;
cuddCacheInsert1(dd,Cudd_addFindMax,f,res);
return(res);
} /* end of Cudd_addFindMax */
/**Function********************************************************************
Synopsis [Finds the minimum discriminant of f.]
Description [Returns a pointer to a constant ADD.]
SideEffects [None]
******************************************************************************/
DdNode *
Cudd_addFindMin(
DdManager * dd,
DdNode * f)
{
DdNode *t, *e, *res;
statLine(dd);
if (cuddIsConstant(f)) {
return(f);
}
res = cuddCacheLookup1(dd,Cudd_addFindMin,f);
if (res != NULL) {
return(res);
}
t = Cudd_addFindMin(dd,cuddT(f));
if (t == DD_MINUS_INFINITY(dd)) return(t);
e = Cudd_addFindMin(dd,cuddE(f));
res = (cuddV(t) <= cuddV(e)) ? t : e;
cuddCacheInsert1(dd,Cudd_addFindMin,f,res);
return(res);
} /* end of Cudd_addFindMin */
/**Function********************************************************************
Synopsis [Extracts the i-th bit from an ADD.]
Description [Produces an ADD from another ADD by replacing all
discriminants whose i-th bit is equal to 1 with 1, and all other
discriminants with 0. The i-th bit refers to the integer
representation of the leaf value. If the value is has a fractional
part, it is ignored. Repeated calls to this procedure allow one to
transform an integer-valued ADD into an array of ADDs, one for each
bit of the leaf values. Returns a pointer to the resulting ADD if
successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_addBddIthBit]
******************************************************************************/
DdNode *
Cudd_addIthBit(
DdManager * dd,
DdNode * f,
int bit)
{
DdNode *res;
DdNode *index;
/* Use a constant node to remember the bit, so that we can use the
** global cache.
*/
index = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) bit);
if (index == NULL) return(NULL);
cuddRef(index);
do {
dd->reordered = 0;
res = addDoIthBit(dd, f, index);
} while (dd->reordered == 1);
if (res == NULL) {
Cudd_RecursiveDeref(dd, index);
return(NULL);
}
cuddRef(res);
Cudd_RecursiveDeref(dd, index);
cuddDeref(res);
return(res);
} /* end of Cudd_addIthBit */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Performs the recursive step for Cudd_addIthBit.]
Description [Performs the recursive step for Cudd_addIthBit.
Returns a pointer to the BDD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static DdNode *
addDoIthBit(
DdManager * dd,
DdNode * f,
DdNode * index)
{
DdNode *res, *T, *E;
DdNode *fv, *fvn;
int mask, value;
int v;
statLine(dd);
/* Check terminal case. */
if (cuddIsConstant(f)) {
mask = 1 << ((int) cuddV(index));
value = (int) cuddV(f);
return((value & mask) == 0 ? DD_ZERO(dd) : DD_ONE(dd));
}
/* Check cache. */
res = cuddCacheLookup2(dd,addDoIthBit,f,index);
if (res != NULL) return(res);
/* Recursive step. */
v = f->index;
fv = cuddT(f); fvn = cuddE(f);
T = addDoIthBit(dd,fv,index);
if (T == NULL) return(NULL);
cuddRef(T);
E = addDoIthBit(dd,fvn,index);
if (E == NULL) {
Cudd_RecursiveDeref(dd, T);
return(NULL);
}
cuddRef(E);
res = (T == E) ? T : cuddUniqueInter(dd,v,T,E);
if (res == NULL) {
Cudd_RecursiveDeref(dd, T);
Cudd_RecursiveDeref(dd, E);
return(NULL);
}
cuddDeref(T);
cuddDeref(E);
/* Store result. */
cuddCacheInsert2(dd,addDoIthBit,f,index,res);
return(res);
} /* end of addDoIthBit */

View File

@@ -0,0 +1,201 @@
/**CFile***********************************************************************
FileName [cuddAddInv.c]
PackageName [cudd]
Synopsis [Function to compute the scalar inverse of an ADD.]
Description [External procedures included in this module:
<ul>
<li> Cudd_addScalarInverse()
</ul>
Internal procedures included in this module:
<ul>
<li> cuddAddScalarInverseRecur()
</ul>]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddAddInv.c,v 1.10 2012/02/05 01:07:18 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Computes the scalar inverse of an ADD.]
Description [Computes an n ADD where the discriminants are the
multiplicative inverses of the corresponding discriminants of the
argument ADD. Returns a pointer to the resulting ADD in case of
success. Returns NULL if any discriminants smaller than epsilon is
encountered.]
SideEffects [None]
******************************************************************************/
DdNode *
Cudd_addScalarInverse(
DdManager * dd,
DdNode * f,
DdNode * epsilon)
{
DdNode *res;
if (!cuddIsConstant(epsilon)) {
(void) fprintf(dd->err,"Invalid epsilon\n");
return(NULL);
}
do {
dd->reordered = 0;
res = cuddAddScalarInverseRecur(dd,f,epsilon);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_addScalarInverse */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Performs the recursive step of addScalarInverse.]
Description [Returns a pointer to the resulting ADD in case of
success. Returns NULL if any discriminants smaller than epsilon is
encountered.]
SideEffects [None]
******************************************************************************/
DdNode *
cuddAddScalarInverseRecur(
DdManager * dd,
DdNode * f,
DdNode * epsilon)
{
DdNode *t, *e, *res;
CUDD_VALUE_TYPE value;
statLine(dd);
if (cuddIsConstant(f)) {
if (ddAbs(cuddV(f)) < cuddV(epsilon)) return(NULL);
value = 1.0 / cuddV(f);
res = cuddUniqueConst(dd,value);
return(res);
}
res = cuddCacheLookup2(dd,Cudd_addScalarInverse,f,epsilon);
if (res != NULL) return(res);
t = cuddAddScalarInverseRecur(dd,cuddT(f),epsilon);
if (t == NULL) return(NULL);
cuddRef(t);
e = cuddAddScalarInverseRecur(dd,cuddE(f),epsilon);
if (e == NULL) {
Cudd_RecursiveDeref(dd, t);
return(NULL);
}
cuddRef(e);
res = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e);
if (res == NULL) {
Cudd_RecursiveDeref(dd, t);
Cudd_RecursiveDeref(dd, e);
return(NULL);
}
cuddDeref(t);
cuddDeref(e);
cuddCacheInsert2(dd,Cudd_addScalarInverse,f,epsilon,res);
return(res);
} /* end of cuddAddScalarInverseRecur */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/

View File

@@ -0,0 +1,639 @@
/**CFile***********************************************************************
FileName [cuddAddIte.c]
PackageName [cudd]
Synopsis [ADD ITE function and satellites.]
Description [External procedures included in this module:
<ul>
<li> Cudd_addIte()
<li> Cudd_addIteConstant()
<li> Cudd_addEvalConst()
<li> Cudd_addCmpl()
<li> Cudd_addLeq()
</ul>
Internal procedures included in this module:
<ul>
<li> cuddAddIteRecur()
<li> cuddAddCmplRecur()
</ul>
Static procedures included in this module:
<ul>
<li> addVarToConst()
</ul>]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddAddIte.c,v 1.16 2012/02/05 01:07:18 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static void addVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *one, DdNode *zero);
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Implements ITE(f,g,h).]
Description [Implements ITE(f,g,h). This procedure assumes that f is
a 0-1 ADD. Returns a pointer to the resulting ADD if successful; NULL
otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddIte Cudd_addIteConstant Cudd_addApply]
******************************************************************************/
DdNode *
Cudd_addIte(
DdManager * dd,
DdNode * f,
DdNode * g,
DdNode * h)
{
DdNode *res;
do {
dd->reordered = 0;
res = cuddAddIteRecur(dd,f,g,h);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_addIte */
/**Function********************************************************************
Synopsis [Implements ITEconstant for ADDs.]
Description [Implements ITEconstant for ADDs. f must be a 0-1 ADD.
Returns a pointer to the resulting ADD (which may or may not be
constant) or DD_NON_CONSTANT. No new nodes are created. This function
can be used, for instance, to check that g has a constant value
(specified by h) whenever f is 1. If the constant value is unknown,
then one should use Cudd_addEvalConst.]
SideEffects [None]
SeeAlso [Cudd_addIte Cudd_addEvalConst Cudd_bddIteConstant]
******************************************************************************/
DdNode *
Cudd_addIteConstant(
DdManager * dd,
DdNode * f,
DdNode * g,
DdNode * h)
{
DdNode *one,*zero;
DdNode *Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*r,*t,*e;
unsigned int topf,topg,toph,v;
statLine(dd);
/* Trivial cases. */
if (f == (one = DD_ONE(dd))) { /* ITE(1,G,H) = G */
return(g);
}
if (f == (zero = DD_ZERO(dd))) { /* ITE(0,G,H) = H */
return(h);
}
/* From now on, f is known not to be a constant. */
addVarToConst(f,&g,&h,one,zero);
/* Check remaining one variable cases. */
if (g == h) { /* ITE(F,G,G) = G */
return(g);
}
if (cuddIsConstant(g) && cuddIsConstant(h)) {
return(DD_NON_CONSTANT);
}
topf = cuddI(dd,f->index);
topg = cuddI(dd,g->index);
toph = cuddI(dd,h->index);
v = ddMin(topg,toph);
/* ITE(F,G,H) = (x,G,H) (non constant) if F = (x,1,0), x < top(G,H). */
if (topf < v && cuddIsConstant(cuddT(f)) && cuddIsConstant(cuddE(f))) {
return(DD_NON_CONSTANT);
}
/* Check cache. */
r = cuddConstantLookup(dd,DD_ADD_ITE_CONSTANT_TAG,f,g,h);
if (r != NULL) {
return(r);
}
/* Compute cofactors. */
if (topf <= v) {
v = ddMin(topf,v); /* v = top_var(F,G,H) */
Fv = cuddT(f); Fnv = cuddE(f);
} else {
Fv = Fnv = f;
}
if (topg == v) {
Gv = cuddT(g); Gnv = cuddE(g);
} else {
Gv = Gnv = g;
}
if (toph == v) {
Hv = cuddT(h); Hnv = cuddE(h);
} else {
Hv = Hnv = h;
}
/* Recursive step. */
t = Cudd_addIteConstant(dd,Fv,Gv,Hv);
if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) {
cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT);
return(DD_NON_CONSTANT);
}
e = Cudd_addIteConstant(dd,Fnv,Gnv,Hnv);
if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) {
cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT);
return(DD_NON_CONSTANT);
}
cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, t);
return(t);
} /* end of Cudd_addIteConstant */
/**Function********************************************************************
Synopsis [Checks whether ADD g is constant whenever ADD f is 1.]
Description [Checks whether ADD g is constant whenever ADD f is 1. f
must be a 0-1 ADD. Returns a pointer to the resulting ADD (which may
or may not be constant) or DD_NON_CONSTANT. If f is identically 0,
the check is assumed to be successful, and the background value is
returned. No new nodes are created.]
SideEffects [None]
SeeAlso [Cudd_addIteConstant Cudd_addLeq]
******************************************************************************/
DdNode *
Cudd_addEvalConst(
DdManager * dd,
DdNode * f,
DdNode * g)
{
DdNode *zero;
DdNode *Fv,*Fnv,*Gv,*Gnv,*r,*t,*e;
unsigned int topf,topg;
#ifdef DD_DEBUG
assert(!Cudd_IsComplement(f));
#endif
statLine(dd);
/* Terminal cases. */
if (f == DD_ONE(dd) || cuddIsConstant(g)) {
return(g);
}
if (f == (zero = DD_ZERO(dd))) {
return(dd->background);
}
#ifdef DD_DEBUG
assert(!cuddIsConstant(f));
#endif
/* From now on, f and g are known not to be constants. */
topf = cuddI(dd,f->index);
topg = cuddI(dd,g->index);
/* Check cache. */
r = cuddConstantLookup(dd,DD_ADD_EVAL_CONST_TAG,f,g,g);
if (r != NULL) {
return(r);
}
/* Compute cofactors. */
if (topf <= topg) {
Fv = cuddT(f); Fnv = cuddE(f);
} else {
Fv = Fnv = f;
}
if (topg <= topf) {
Gv = cuddT(g); Gnv = cuddE(g);
} else {
Gv = Gnv = g;
}
/* Recursive step. */
if (Fv != zero) {
t = Cudd_addEvalConst(dd,Fv,Gv);
if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) {
cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, DD_NON_CONSTANT);
return(DD_NON_CONSTANT);
}
if (Fnv != zero) {
e = Cudd_addEvalConst(dd,Fnv,Gnv);
if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) {
cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, DD_NON_CONSTANT);
return(DD_NON_CONSTANT);
}
}
cuddCacheInsert2(dd,Cudd_addEvalConst,f,g,t);
return(t);
} else { /* Fnv must be != zero */
e = Cudd_addEvalConst(dd,Fnv,Gnv);
cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, e);
return(e);
}
} /* end of Cudd_addEvalConst */
/**Function********************************************************************
Synopsis [Computes the complement of an ADD a la C language.]
Description [Computes the complement of an ADD a la C language: The
complement of 0 is 1 and the complement of everything else is 0.
Returns a pointer to the resulting ADD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_addNegate]
******************************************************************************/
DdNode *
Cudd_addCmpl(
DdManager * dd,
DdNode * f)
{
DdNode *res;
do {
dd->reordered = 0;
res = cuddAddCmplRecur(dd,f);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_addCmpl */
/**Function********************************************************************
Synopsis [Determines whether f is less than or equal to g.]
Description [Returns 1 if f is less than or equal to g; 0 otherwise.
No new nodes are created. This procedure works for arbitrary ADDs.
For 0-1 ADDs Cudd_addEvalConst is more efficient.]
SideEffects [None]
SeeAlso [Cudd_addIteConstant Cudd_addEvalConst Cudd_bddLeq]
******************************************************************************/
int
Cudd_addLeq(
DdManager * dd,
DdNode * f,
DdNode * g)
{
DdNode *tmp, *fv, *fvn, *gv, *gvn;
unsigned int topf, topg, res;
/* Terminal cases. */
if (f == g) return(1);
statLine(dd);
if (cuddIsConstant(f)) {
if (cuddIsConstant(g)) return(cuddV(f) <= cuddV(g));
if (f == DD_MINUS_INFINITY(dd)) return(1);
if (f == DD_PLUS_INFINITY(dd)) return(0); /* since f != g */
}
if (g == DD_PLUS_INFINITY(dd)) return(1);
if (g == DD_MINUS_INFINITY(dd)) return(0); /* since f != g */
/* Check cache. */
tmp = cuddCacheLookup2(dd,(DD_CTFP)Cudd_addLeq,f,g);
if (tmp != NULL) {
return(tmp == DD_ONE(dd));
}
/* Compute cofactors. One of f and g is not constant. */
topf = cuddI(dd,f->index);
topg = cuddI(dd,g->index);
if (topf <= topg) {
fv = cuddT(f); fvn = cuddE(f);
} else {
fv = fvn = f;
}
if (topg <= topf) {
gv = cuddT(g); gvn = cuddE(g);
} else {
gv = gvn = g;
}
res = Cudd_addLeq(dd,fvn,gvn) && Cudd_addLeq(dd,fv,gv);
/* Store result in cache and return. */
cuddCacheInsert2(dd,(DD_CTFP) Cudd_addLeq,f,g,
Cudd_NotCond(DD_ONE(dd),res==0));
return(res);
} /* end of Cudd_addLeq */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Implements the recursive step of Cudd_addIte(f,g,h).]
Description [Implements the recursive step of Cudd_addIte(f,g,h).
Returns a pointer to the resulting ADD if successful; NULL
otherwise.]
SideEffects [None]
SeeAlso [Cudd_addIte]
******************************************************************************/
DdNode *
cuddAddIteRecur(
DdManager * dd,
DdNode * f,
DdNode * g,
DdNode * h)
{
DdNode *one,*zero;
DdNode *r,*Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*t,*e;
unsigned int topf,topg,toph,v;
int index;
statLine(dd);
/* Trivial cases. */
/* One variable cases. */
if (f == (one = DD_ONE(dd))) { /* ITE(1,G,H) = G */
return(g);
}
if (f == (zero = DD_ZERO(dd))) { /* ITE(0,G,H) = H */
return(h);
}
/* From now on, f is known to not be a constant. */
addVarToConst(f,&g,&h,one,zero);
/* Check remaining one variable cases. */
if (g == h) { /* ITE(F,G,G) = G */
return(g);
}
if (g == one) { /* ITE(F,1,0) = F */
if (h == zero) return(f);
}
topf = cuddI(dd,f->index);
topg = cuddI(dd,g->index);
toph = cuddI(dd,h->index);
v = ddMin(topg,toph);
/* A shortcut: ITE(F,G,H) = (x,G,H) if F=(x,1,0), x < top(G,H). */
if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
r = cuddUniqueInter(dd,(int)f->index,g,h);
return(r);
}
if (topf < v && cuddT(f) == zero && cuddE(f) == one) {
r = cuddUniqueInter(dd,(int)f->index,h,g);
return(r);
}
/* Check cache. */
r = cuddCacheLookup(dd,DD_ADD_ITE_TAG,f,g,h);
if (r != NULL) {
return(r);
}
/* Compute cofactors. */
if (topf <= v) {
v = ddMin(topf,v); /* v = top_var(F,G,H) */
index = f->index;
Fv = cuddT(f); Fnv = cuddE(f);
} else {
Fv = Fnv = f;
}
if (topg == v) {
index = g->index;
Gv = cuddT(g); Gnv = cuddE(g);
} else {
Gv = Gnv = g;
}
if (toph == v) {
index = h->index;
Hv = cuddT(h); Hnv = cuddE(h);
} else {
Hv = Hnv = h;
}
/* Recursive step. */
t = cuddAddIteRecur(dd,Fv,Gv,Hv);
if (t == NULL) return(NULL);
cuddRef(t);
e = cuddAddIteRecur(dd,Fnv,Gnv,Hnv);
if (e == NULL) {
Cudd_RecursiveDeref(dd,t);
return(NULL);
}
cuddRef(e);
r = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
if (r == NULL) {
Cudd_RecursiveDeref(dd,t);
Cudd_RecursiveDeref(dd,e);
return(NULL);
}
cuddDeref(t);
cuddDeref(e);
cuddCacheInsert(dd,DD_ADD_ITE_TAG,f,g,h,r);
return(r);
} /* end of cuddAddIteRecur */
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_addCmpl.]
Description [Performs the recursive step of Cudd_addCmpl. Returns a
pointer to the resulting ADD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_addCmpl]
******************************************************************************/
DdNode *
cuddAddCmplRecur(
DdManager * dd,
DdNode * f)
{
DdNode *one,*zero;
DdNode *r,*Fv,*Fnv,*t,*e;
statLine(dd);
one = DD_ONE(dd);
zero = DD_ZERO(dd);
if (cuddIsConstant(f)) {
if (f == zero) {
return(one);
} else {
return(zero);
}
}
r = cuddCacheLookup1(dd,Cudd_addCmpl,f);
if (r != NULL) {
return(r);
}
Fv = cuddT(f);
Fnv = cuddE(f);
t = cuddAddCmplRecur(dd,Fv);
if (t == NULL) return(NULL);
cuddRef(t);
e = cuddAddCmplRecur(dd,Fnv);
if (e == NULL) {
Cudd_RecursiveDeref(dd,t);
return(NULL);
}
cuddRef(e);
r = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e);
if (r == NULL) {
Cudd_RecursiveDeref(dd, t);
Cudd_RecursiveDeref(dd, e);
return(NULL);
}
cuddDeref(t);
cuddDeref(e);
cuddCacheInsert1(dd,Cudd_addCmpl,f,r);
return(r);
} /* end of cuddAddCmplRecur */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Replaces variables with constants if possible (part of
canonical form).]
Description []
SideEffects [None]
******************************************************************************/
static void
addVarToConst(
DdNode * f,
DdNode ** gp,
DdNode ** hp,
DdNode * one,
DdNode * zero)
{
DdNode *g = *gp;
DdNode *h = *hp;
if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */
*gp = one;
}
if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */
*hp = zero;
}
} /* end of addVarToConst */

View File

@@ -0,0 +1,290 @@
/**CFile***********************************************************************
FileName [cuddAddNeg.c]
PackageName [cudd]
Synopsis [Function to compute the negation of an ADD.]
Description [External procedures included in this module:
<ul>
<li> Cudd_addNegate()
<li> Cudd_addRoundOff()
</ul>
Internal procedures included in this module:
<ul>
<li> cuddAddNegateRecur()
<li> cuddAddRoundOffRecur()
</ul> ]
Author [Fabio Somenzi, Balakrishna Kumthekar]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddAddNeg.c,v 1.14 2012/02/05 01:07:18 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Computes the additive inverse of an ADD.]
Description [Computes the additive inverse of an ADD. Returns a pointer
to the result if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_addCmpl]
******************************************************************************/
DdNode *
Cudd_addNegate(
DdManager * dd,
DdNode * f)
{
DdNode *res;
do {
dd->reordered = 0;
res = cuddAddNegateRecur(dd,f);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_addNegate */
/**Function********************************************************************
Synopsis [Rounds off the discriminants of an ADD.]
Description [Rounds off the discriminants of an ADD. The discriminants are
rounded off to N digits after the decimal. Returns a pointer to the result
ADD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
DdNode *
Cudd_addRoundOff(
DdManager * dd,
DdNode * f,
int N)
{
DdNode *res;
double trunc = pow(10.0,(double)N);
do {
dd->reordered = 0;
res = cuddAddRoundOffRecur(dd,f,trunc);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_addRoundOff */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Implements the recursive step of Cudd_addNegate.]
Description [Implements the recursive step of Cudd_addNegate.
Returns a pointer to the result.]
SideEffects [None]
******************************************************************************/
DdNode *
cuddAddNegateRecur(
DdManager * dd,
DdNode * f)
{
DdNode *res,
*fv, *fvn,
*T, *E;
statLine(dd);
/* Check terminal cases. */
if (cuddIsConstant(f)) {
res = cuddUniqueConst(dd,-cuddV(f));
return(res);
}
/* Check cache */
res = cuddCacheLookup1(dd,Cudd_addNegate,f);
if (res != NULL) return(res);
/* Recursive Step */
fv = cuddT(f);
fvn = cuddE(f);
T = cuddAddNegateRecur(dd,fv);
if (T == NULL) return(NULL);
cuddRef(T);
E = cuddAddNegateRecur(dd,fvn);
if (E == NULL) {
Cudd_RecursiveDeref(dd,T);
return(NULL);
}
cuddRef(E);
res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E);
if (res == NULL) {
Cudd_RecursiveDeref(dd, T);
Cudd_RecursiveDeref(dd, E);
return(NULL);
}
cuddDeref(T);
cuddDeref(E);
/* Store result. */
cuddCacheInsert1(dd,Cudd_addNegate,f,res);
return(res);
} /* end of cuddAddNegateRecur */
/**Function********************************************************************
Synopsis [Implements the recursive step of Cudd_addRoundOff.]
Description [Implements the recursive step of Cudd_addRoundOff.
Returns a pointer to the result.]
SideEffects [None]
******************************************************************************/
DdNode *
cuddAddRoundOffRecur(
DdManager * dd,
DdNode * f,
double trunc)
{
DdNode *res, *fv, *fvn, *T, *E;
double n;
DD_CTFP1 cacheOp;
statLine(dd);
if (cuddIsConstant(f)) {
n = ceil(cuddV(f)*trunc)/trunc;
res = cuddUniqueConst(dd,n);
return(res);
}
cacheOp = (DD_CTFP1) Cudd_addRoundOff;
res = cuddCacheLookup1(dd,cacheOp,f);
if (res != NULL) {
return(res);
}
/* Recursive Step */
fv = cuddT(f);
fvn = cuddE(f);
T = cuddAddRoundOffRecur(dd,fv,trunc);
if (T == NULL) {
return(NULL);
}
cuddRef(T);
E = cuddAddRoundOffRecur(dd,fvn,trunc);
if (E == NULL) {
Cudd_RecursiveDeref(dd,T);
return(NULL);
}
cuddRef(E);
res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E);
if (res == NULL) {
Cudd_RecursiveDeref(dd,T);
Cudd_RecursiveDeref(dd,E);
return(NULL);
}
cuddDeref(T);
cuddDeref(E);
/* Store result. */
cuddCacheInsert1(dd,cacheOp,f,res);
return(res);
} /* end of cuddAddRoundOffRecur */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/

View File

@@ -0,0 +1,391 @@
/**CFile***********************************************************************
FileName [cuddAddWalsh.c]
PackageName [cudd]
Synopsis [Functions that generate Walsh matrices and residue
functions in ADD form.]
Description [External procedures included in this module:
<ul>
<li> Cudd_addWalsh()
<li> Cudd_addResidue()
</ul>
Static procedures included in this module:
<ul>
<li> addWalshInt()
</ul>]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddAddWalsh.c,v 1.11 2012/02/05 01:07:18 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static DdNode * addWalshInt (DdManager *dd, DdNode **x, DdNode **y, int n);
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Generates a Walsh matrix in ADD form.]
Description [Generates a Walsh matrix in ADD form. Returns a pointer
to the matrixi if successful; NULL otherwise.]
SideEffects [None]
******************************************************************************/
DdNode *
Cudd_addWalsh(
DdManager * dd,
DdNode ** x,
DdNode ** y,
int n)
{
DdNode *res;
do {
dd->reordered = 0;
res = addWalshInt(dd, x, y, n);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_addWalsh */
/**Function********************************************************************
Synopsis [Builds an ADD for the residue modulo m of an n-bit
number.]
Description [Builds an ADD for the residue modulo m of an n-bit
number. The modulus must be at least 2, and the number of bits at
least 1. Parameter options specifies whether the MSB should be on top
or the LSB; and whther the number whose residue is computed is in
two's complement notation or not. The macro CUDD_RESIDUE_DEFAULT
specifies LSB on top and unsigned number. The macro CUDD_RESIDUE_MSB
specifies MSB on top, and the macro CUDD_RESIDUE_TC specifies two's
complement residue. To request MSB on top and two's complement residue
simultaneously, one can OR the two macros:
CUDD_RESIDUE_MSB | CUDD_RESIDUE_TC.
Cudd_addResidue returns a pointer to the resulting ADD if successful;
NULL otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
DdNode *
Cudd_addResidue(
DdManager * dd /* manager */,
int n /* number of bits */,
int m /* modulus */,
int options /* options */,
int top /* index of top variable */)
{
int msbLsb; /* MSB on top (1) or LSB on top (0) */
int tc; /* two's complement (1) or unsigned (0) */
int i, j, k, t, residue, thisOne, previous, index;
DdNode **array[2], *var, *tmp, *res;
/* Sanity check. */
if (n < 1 && m < 2) return(NULL);
msbLsb = options & CUDD_RESIDUE_MSB;
tc = options & CUDD_RESIDUE_TC;
/* Allocate and initialize working arrays. */
array[0] = ALLOC(DdNode *,m);
if (array[0] == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(NULL);
}
array[1] = ALLOC(DdNode *,m);
if (array[1] == NULL) {
FREE(array[0]);
dd->errorCode = CUDD_MEMORY_OUT;
return(NULL);
}
for (i = 0; i < m; i++) {
array[0][i] = array[1][i] = NULL;
}
/* Initialize residues. */
for (i = 0; i < m; i++) {
tmp = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) i);
if (tmp == NULL) {
for (j = 0; j < i; j++) {
Cudd_RecursiveDeref(dd,array[1][j]);
}
FREE(array[0]);
FREE(array[1]);
return(NULL);
}
cuddRef(tmp);
array[1][i] = tmp;
}
/* Main iteration. */
residue = 1; /* residue of 2**0 */
for (k = 0; k < n; k++) {
/* Choose current and previous arrays. */
thisOne = k & 1;
previous = thisOne ^ 1;
/* Build an ADD projection function. */
if (msbLsb) {
index = top+n-k-1;
} else {
index = top+k;
}
var = cuddUniqueInter(dd,index,DD_ONE(dd),DD_ZERO(dd));
if (var == NULL) {
for (j = 0; j < m; j++) {
Cudd_RecursiveDeref(dd,array[previous][j]);
}
FREE(array[0]);
FREE(array[1]);
return(NULL);
}
cuddRef(var);
for (i = 0; i < m; i ++) {
t = (i + residue) % m;
tmp = Cudd_addIte(dd,var,array[previous][t],array[previous][i]);
if (tmp == NULL) {
for (j = 0; j < i; j++) {
Cudd_RecursiveDeref(dd,array[thisOne][j]);
}
for (j = 0; j < m; j++) {
Cudd_RecursiveDeref(dd,array[previous][j]);
}
FREE(array[0]);
FREE(array[1]);
return(NULL);
}
cuddRef(tmp);
array[thisOne][i] = tmp;
}
/* One layer completed. Free the other array for the next iteration. */
for (i = 0; i < m; i++) {
Cudd_RecursiveDeref(dd,array[previous][i]);
}
Cudd_RecursiveDeref(dd,var);
/* Update residue of 2**k. */
residue = (2 * residue) % m;
/* Adjust residue for MSB, if this is a two's complement number. */
if (tc && (k == n - 1)) {
residue = (m - residue) % m;
}
}
/* We are only interested in the 0-residue node of the top layer. */
for (i = 1; i < m; i++) {
Cudd_RecursiveDeref(dd,array[(n - 1) & 1][i]);
}
res = array[(n - 1) & 1][0];
FREE(array[0]);
FREE(array[1]);
cuddDeref(res);
return(res);
} /* end of Cudd_addResidue */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Implements the recursive step of Cudd_addWalsh.]
Description [Generates a Walsh matrix in ADD form. Returns a pointer
to the matrixi if successful; NULL otherwise.]
SideEffects [None]
******************************************************************************/
static DdNode *
addWalshInt(
DdManager * dd,
DdNode ** x,
DdNode ** y,
int n)
{
DdNode *one, *minusone;
DdNode *t, *u, *t1, *u1, *v, *w;
int i;
one = DD_ONE(dd);
if (n == 0) return(one);
/* Build bottom part of ADD outside loop */
minusone = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) -1);
if (minusone == NULL) return(NULL);
cuddRef(minusone);
v = Cudd_addIte(dd, y[n-1], minusone, one);
if (v == NULL) {
Cudd_RecursiveDeref(dd, minusone);
return(NULL);
}
cuddRef(v);
u = Cudd_addIte(dd, x[n-1], v, one);
if (u == NULL) {
Cudd_RecursiveDeref(dd, minusone);
Cudd_RecursiveDeref(dd, v);
return(NULL);
}
cuddRef(u);
Cudd_RecursiveDeref(dd, v);
if (n>1) {
w = Cudd_addIte(dd, y[n-1], one, minusone);
if (w == NULL) {
Cudd_RecursiveDeref(dd, minusone);
Cudd_RecursiveDeref(dd, u);
return(NULL);
}
cuddRef(w);
t = Cudd_addIte(dd, x[n-1], w, minusone);
if (t == NULL) {
Cudd_RecursiveDeref(dd, minusone);
Cudd_RecursiveDeref(dd, u);
Cudd_RecursiveDeref(dd, w);
return(NULL);
}
cuddRef(t);
Cudd_RecursiveDeref(dd, w);
}
cuddDeref(minusone); /* minusone is in the result; it won't die */
/* Loop to build the rest of the ADD */
for (i=n-2; i>=0; i--) {
t1 = t; u1 = u;
v = Cudd_addIte(dd, y[i], t1, u1);
if (v == NULL) {
Cudd_RecursiveDeref(dd, u1);
Cudd_RecursiveDeref(dd, t1);
return(NULL);
}
cuddRef(v);
u = Cudd_addIte(dd, x[i], v, u1);
if (u == NULL) {
Cudd_RecursiveDeref(dd, u1);
Cudd_RecursiveDeref(dd, t1);
Cudd_RecursiveDeref(dd, v);
return(NULL);
}
cuddRef(u);
Cudd_RecursiveDeref(dd, v);
if (i>0) {
w = Cudd_addIte(dd, y[i], u1, t1);
if (w == NULL) {
Cudd_RecursiveDeref(dd, u1);
Cudd_RecursiveDeref(dd, t1);
Cudd_RecursiveDeref(dd, u);
return(NULL);
}
cuddRef(w);
t = Cudd_addIte(dd, x[i], w, t1);
if (u == NULL) {
Cudd_RecursiveDeref(dd, u1);
Cudd_RecursiveDeref(dd, t1);
Cudd_RecursiveDeref(dd, u);
Cudd_RecursiveDeref(dd, w);
return(NULL);
}
cuddRef(t);
Cudd_RecursiveDeref(dd, w);
}
Cudd_RecursiveDeref(dd, u1);
Cudd_RecursiveDeref(dd, t1);
}
cuddDeref(u);
return(u);
} /* end of addWalshInt */

View File

@@ -0,0 +1,373 @@
/**CFile***********************************************************************
FileName [cuddAndAbs.c]
PackageName [cudd]
Synopsis [Combined AND and existential abstraction for BDDs]
Description [External procedures included in this module:
<ul>
<li> Cudd_bddAndAbstract()
<li> Cudd_bddAndAbstractLimit()
</ul>
Internal procedures included in this module:
<ul>
<li> cuddBddAndAbstractRecur()
</ul>]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddAndAbs.c,v 1.20 2012/02/05 01:07:18 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
variables in cube.]
Description [Takes the AND of two BDDs and simultaneously abstracts
the variables in cube. The variables are existentially abstracted.
Returns a pointer to the result is successful; NULL otherwise.
Cudd_bddAndAbstract implements the semiring matrix multiplication
algorithm for the boolean semiring.]
SideEffects [None]
SeeAlso [Cudd_addMatrixMultiply Cudd_addTriangle Cudd_bddAnd]
******************************************************************************/
DdNode *
Cudd_bddAndAbstract(
DdManager * manager,
DdNode * f,
DdNode * g,
DdNode * cube)
{
DdNode *res;
do {
manager->reordered = 0;
res = cuddBddAndAbstractRecur(manager, f, g, cube);
} while (manager->reordered == 1);
return(res);
} /* end of Cudd_bddAndAbstract */
/**Function********************************************************************
Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
variables in cube. Returns NULL if too many nodes are required.]
Description [Takes the AND of two BDDs and simultaneously abstracts
the variables in cube. The variables are existentially abstracted.
Returns a pointer to the result is successful; NULL otherwise.
In particular, if the number of new nodes created exceeds
<code>limit</code>, this function returns NULL.]
SideEffects [None]
SeeAlso [Cudd_bddAndAbstract]
******************************************************************************/
DdNode *
Cudd_bddAndAbstractLimit(
DdManager * manager,
DdNode * f,
DdNode * g,
DdNode * cube,
unsigned int limit)
{
DdNode *res;
unsigned int saveLimit = manager->maxLive;
manager->maxLive = (manager->keys - manager->dead) +
(manager->keysZ - manager->deadZ) + limit;
do {
manager->reordered = 0;
res = cuddBddAndAbstractRecur(manager, f, g, cube);
} while (manager->reordered == 1);
manager->maxLive = saveLimit;
return(res);
} /* end of Cudd_bddAndAbstractLimit */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
variables in cube.]
Description [Takes the AND of two BDDs and simultaneously abstracts
the variables in cube. The variables are existentially abstracted.
Returns a pointer to the result is successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddAndAbstract]
******************************************************************************/
DdNode *
cuddBddAndAbstractRecur(
DdManager * manager,
DdNode * f,
DdNode * g,
DdNode * cube)
{
DdNode *F, *ft, *fe, *G, *gt, *ge;
DdNode *one, *zero, *r, *t, *e;
unsigned int topf, topg, topcube, top, index;
statLine(manager);
one = DD_ONE(manager);
zero = Cudd_Not(one);
/* Terminal cases. */
if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
if (f == one && g == one) return(one);
if (cube == one) {
return(cuddBddAndRecur(manager, f, g));
}
if (f == one || f == g) {
return(cuddBddExistAbstractRecur(manager, g, cube));
}
if (g == one) {
return(cuddBddExistAbstractRecur(manager, f, cube));
}
/* At this point f, g, and cube are not constant. */
if (f > g) { /* Try to increase cache efficiency. */
DdNode *tmp = f;
f = g;
g = tmp;
}
/* Here we can skip the use of cuddI, because the operands are known
** to be non-constant.
*/
F = Cudd_Regular(f);
G = Cudd_Regular(g);
topf = manager->perm[F->index];
topg = manager->perm[G->index];
top = ddMin(topf, topg);
topcube = manager->perm[cube->index];
while (topcube < top) {
cube = cuddT(cube);
if (cube == one) {
return(cuddBddAndRecur(manager, f, g));
}
topcube = manager->perm[cube->index];
}
/* Now, topcube >= top. */
/* Check cache. */
if (F->ref != 1 || G->ref != 1) {
r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube);
if (r != NULL) {
return(r);
}
}
if (topf == top) {
index = F->index;
ft = cuddT(F);
fe = cuddE(F);
if (Cudd_IsComplement(f)) {
ft = Cudd_Not(ft);
fe = Cudd_Not(fe);
}
} else {
index = G->index;
ft = fe = f;
}
if (topg == top) {
gt = cuddT(G);
ge = cuddE(G);
if (Cudd_IsComplement(g)) {
gt = Cudd_Not(gt);
ge = Cudd_Not(ge);
}
} else {
gt = ge = g;
}
if (topcube == top) { /* quantify */
DdNode *Cube = cuddT(cube);
t = cuddBddAndAbstractRecur(manager, ft, gt, Cube);
if (t == NULL) return(NULL);
/* Special case: 1 OR anything = 1. Hence, no need to compute
** the else branch if t is 1. Likewise t + t * anything == t.
** Notice that t == fe implies that fe does not depend on the
** variables in Cube. Likewise for t == ge.
*/
if (t == one || t == fe || t == ge) {
if (F->ref != 1 || G->ref != 1)
cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG,
f, g, cube, t);
return(t);
}
cuddRef(t);
/* Special case: t + !t * anything == t + anything. */
if (t == Cudd_Not(fe)) {
e = cuddBddExistAbstractRecur(manager, ge, Cube);
} else if (t == Cudd_Not(ge)) {
e = cuddBddExistAbstractRecur(manager, fe, Cube);
} else {
e = cuddBddAndAbstractRecur(manager, fe, ge, Cube);
}
if (e == NULL) {
Cudd_IterDerefBdd(manager, t);
return(NULL);
}
if (t == e) {
r = t;
cuddDeref(t);
} else {
cuddRef(e);
r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e));
if (r == NULL) {
Cudd_IterDerefBdd(manager, t);
Cudd_IterDerefBdd(manager, e);
return(NULL);
}
r = Cudd_Not(r);
cuddRef(r);
Cudd_DelayedDerefBdd(manager, t);
Cudd_DelayedDerefBdd(manager, e);
cuddDeref(r);
}
} else {
t = cuddBddAndAbstractRecur(manager, ft, gt, cube);
if (t == NULL) return(NULL);
cuddRef(t);
e = cuddBddAndAbstractRecur(manager, fe, ge, cube);
if (e == NULL) {
Cudd_IterDerefBdd(manager, t);
return(NULL);
}
if (t == e) {
r = t;
cuddDeref(t);
} else {
cuddRef(e);
if (Cudd_IsComplement(t)) {
r = cuddUniqueInter(manager, (int) index,
Cudd_Not(t), Cudd_Not(e));
if (r == NULL) {
Cudd_IterDerefBdd(manager, t);
Cudd_IterDerefBdd(manager, e);
return(NULL);
}
r = Cudd_Not(r);
} else {
r = cuddUniqueInter(manager,(int)index,t,e);
if (r == NULL) {
Cudd_IterDerefBdd(manager, t);
Cudd_IterDerefBdd(manager, e);
return(NULL);
}
}
cuddDeref(e);
cuddDeref(t);
}
}
if (F->ref != 1 || G->ref != 1)
cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r);
return (r);
} /* end of cuddBddAndAbstractRecur */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/

View File

@@ -0,0 +1,814 @@
/**CFile***********************************************************************
FileName [cuddAnneal.c]
PackageName [cudd]
Synopsis [Reordering of DDs based on simulated annealing]
Description [Internal procedures included in this file:
<ul>
<li> cuddAnnealing()
</ul>
Static procedures included in this file:
<ul>
<li> stopping_criterion()
<li> random_generator()
<li> ddExchange()
<li> ddJumpingAux()
<li> ddJumpingUp()
<li> ddJumpingDown()
<li> siftBackwardProb()
<li> copyOrder()
<li> restoreOrder()
</ul>
]
SeeAlso []
Author [Jae-Young Jang, Jorgen Sivesind]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/* Annealing parameters */
#define BETA 0.6
#define ALPHA 0.90
#define EXC_PROB 0.4
#define JUMP_UP_PROB 0.36
#define MAXGEN_RATIO 15.0
#define STOP_TEMP 1.0
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddAnneal.c,v 1.15 2012/02/05 01:07:18 fabio Exp $";
#endif
#ifdef DD_STATS
extern int ddTotalNumberSwapping;
extern int ddTotalNISwaps;
static int tosses;
static int acceptances;
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static int stopping_criterion (int c1, int c2, int c3, int c4, double temp);
static double random_generator (void);
static int ddExchange (DdManager *table, int x, int y, double temp);
static int ddJumpingAux (DdManager *table, int x, int x_low, int x_high, double temp);
static Move * ddJumpingUp (DdManager *table, int x, int x_low, int initial_size);
static Move * ddJumpingDown (DdManager *table, int x, int x_high, int initial_size);
static int siftBackwardProb (DdManager *table, Move *moves, int size, double temp);
static void copyOrder (DdManager *table, int *array, int lower, int upper);
static int restoreOrder (DdManager *table, int *array, int lower, int upper);
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Get new variable-order by simulated annealing algorithm.]
Description [Get x, y by random selection. Choose either
exchange or jump randomly. In case of jump, choose between jump_up
and jump_down randomly. Do exchange or jump and get optimal case.
Loop until there is no improvement or temperature reaches
minimum. Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
int
cuddAnnealing(
DdManager * table,
int lower,
int upper)
{
int nvars;
int size;
int x,y;
int result;
int c1, c2, c3, c4;
int BestCost;
int *BestOrder;
double NewTemp, temp;
double rand1;
int innerloop, maxGen;
int ecount, ucount, dcount;
nvars = upper - lower + 1;
result = cuddSifting(table,lower,upper);
#ifdef DD_STATS
(void) fprintf(table->out,"\n");
#endif
if (result == 0) return(0);
size = table->keys - table->isolated;
/* Keep track of the best order. */
BestCost = size;
BestOrder = ALLOC(int,nvars);
if (BestOrder == NULL) {
table->errorCode = CUDD_MEMORY_OUT;
return(0);
}
copyOrder(table,BestOrder,lower,upper);
temp = BETA * size;
maxGen = (int) (MAXGEN_RATIO * nvars);
c1 = size + 10;
c2 = c1 + 10;
c3 = size;
c4 = c2 + 10;
ecount = ucount = dcount = 0;
while (!stopping_criterion(c1, c2, c3, c4, temp)) {
#ifdef DD_STATS
(void) fprintf(table->out,"temp=%f\tsize=%d\tgen=%d\t",
temp,size,maxGen);
tosses = acceptances = 0;
#endif
for (innerloop = 0; innerloop < maxGen; innerloop++) {
/* Choose x, y randomly. */
x = (int) Cudd_Random() % nvars;
do {
y = (int) Cudd_Random() % nvars;
} while (x == y);
x += lower;
y += lower;
if (x > y) {
int tmp = x;
x = y;
y = tmp;
}
/* Choose move with roulette wheel. */
rand1 = random_generator();
if (rand1 < EXC_PROB) {
result = ddExchange(table,x,y,temp); /* exchange */
ecount++;
#if 0
(void) fprintf(table->out,
"Exchange of %d and %d: size = %d\n",
x,y,table->keys - table->isolated);
#endif
} else if (rand1 < EXC_PROB + JUMP_UP_PROB) {
result = ddJumpingAux(table,y,x,y,temp); /* jumping_up */
ucount++;
#if 0
(void) fprintf(table->out,
"Jump up of %d to %d: size = %d\n",
y,x,table->keys - table->isolated);
#endif
} else {
result = ddJumpingAux(table,x,x,y,temp); /* jumping_down */
dcount++;
#if 0
(void) fprintf(table->out,
"Jump down of %d to %d: size = %d\n",
x,y,table->keys - table->isolated);
#endif
}
if (!result) {
FREE(BestOrder);
return(0);
}
size = table->keys - table->isolated; /* keep current size */
if (size < BestCost) { /* update best order */
BestCost = size;
copyOrder(table,BestOrder,lower,upper);
}
}
c1 = c2;
c2 = c3;
c3 = c4;
c4 = size;
NewTemp = ALPHA * temp;
if (NewTemp >= 1.0) {
maxGen = (int)(log(NewTemp) / log(temp) * maxGen);
}
temp = NewTemp; /* control variable */
#ifdef DD_STATS
(void) fprintf(table->out,"uphill = %d\taccepted = %d\n",
tosses,acceptances);
fflush(table->out);
#endif
}
result = restoreOrder(table,BestOrder,lower,upper);
FREE(BestOrder);
if (!result) return(0);
#ifdef DD_STATS
fprintf(table->out,"#:N_EXCHANGE %8d : total exchanges\n",ecount);
fprintf(table->out,"#:N_JUMPUP %8d : total jumps up\n",ucount);
fprintf(table->out,"#:N_JUMPDOWN %8d : total jumps down",dcount);
#endif
return(1);
} /* end of cuddAnnealing */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Checks termination condition.]
Description [If temperature is STOP_TEMP or there is no improvement
then terminates. Returns 1 if the termination criterion is met; 0
otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
stopping_criterion(
int c1,
int c2,
int c3,
int c4,
double temp)
{
if (STOP_TEMP < temp) {
return(0);
} else if ((c1 == c2) && (c1 == c3) && (c1 == c4)) {
return(1);
} else {
return(0);
}
} /* end of stopping_criterion */
/**Function********************************************************************
Synopsis [Random number generator.]
Description [Returns a double precision value between 0.0 and 1.0.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static double
random_generator(void)
{
return((double)(Cudd_Random() / 2147483561.0));
} /* end of random_generator */
/**Function********************************************************************
Synopsis [This function is for exchanging two variables, x and y.]
Description [This is the same funcion as ddSwapping except for
comparison expression. Use probability function, exp(-size_change/temp).]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
ddExchange(
DdManager * table,
int x,
int y,
double temp)
{
Move *move,*moves;
int tmp;
int x_ref,y_ref;
int x_next,y_next;
int size, result;
int initial_size, limit_size;
x_ref = x;
y_ref = y;
x_next = cuddNextHigh(table,x);
y_next = cuddNextLow(table,y);
moves = NULL;
initial_size = limit_size = table->keys - table->isolated;
for (;;) {
if (x_next == y_next) {
size = cuddSwapInPlace(table,x,x_next);
if (size == 0) goto ddExchangeOutOfMem;
move = (Move *)cuddDynamicAllocNode(table);
if (move == NULL) goto ddExchangeOutOfMem;
move->x = x;
move->y = x_next;
move->size = size;
move->next = moves;
moves = move;
size = cuddSwapInPlace(table,y_next,y);
if (size == 0) goto ddExchangeOutOfMem;
move = (Move *)cuddDynamicAllocNode(table);
if (move == NULL) goto ddExchangeOutOfMem;
move->x = y_next;
move->y = y;
move->size = size;
move->next = moves;
moves = move;
size = cuddSwapInPlace(table,x,x_next);
if (size == 0) goto ddExchangeOutOfMem;
move = (Move *)cuddDynamicAllocNode(table);
if (move == NULL) goto ddExchangeOutOfMem;
move->x = x;
move->y = x_next;
move->size = size;
move->next = moves;
moves = move;
tmp = x;
x = y;
y = tmp;
} else if (x == y_next) {
size = cuddSwapInPlace(table,x,x_next);
if (size == 0) goto ddExchangeOutOfMem;
move = (Move *)cuddDynamicAllocNode(table);
if (move == NULL) goto ddExchangeOutOfMem;
move->x = x;
move->y = x_next;
move->size = size;
move->next = moves;
moves = move;
tmp = x;
x = y;
y = tmp;
} else {
size = cuddSwapInPlace(table,x,x_next);
if (size == 0) goto ddExchangeOutOfMem;
move = (Move *)cuddDynamicAllocNode(table);
if (move == NULL) goto ddExchangeOutOfMem;
move->x = x;
move->y = x_next;
move->size = size;
move->next = moves;
moves = move;
size = cuddSwapInPlace(table,y_next,y);
if (size == 0) goto ddExchangeOutOfMem;
move = (Move *)cuddDynamicAllocNode(table);
if (move == NULL) goto ddExchangeOutOfMem;
move->x = y_next;
move->y = y;
move->size = size;
move->next = moves;
moves = move;
x = x_next;
y = y_next;
}
x_next = cuddNextHigh(table,x);
y_next = cuddNextLow(table,y);
if (x_next > y_ref) break;
if ((double) size > DD_MAX_REORDER_GROWTH * (double) limit_size) {
break;
} else if (size < limit_size) {
limit_size = size;
}
}
if (y_next>=x_ref) {
size = cuddSwapInPlace(table,y_next,y);
if (size == 0) goto ddExchangeOutOfMem;
move = (Move *)cuddDynamicAllocNode(table);
if (move == NULL) goto ddExchangeOutOfMem;
move->x = y_next;
move->y = y;
move->size = size;
move->next = moves;
moves = move;
}
/* move backward and stop at best position or accept uphill move */
result = siftBackwardProb(table,moves,initial_size,temp);
if (!result) goto ddExchangeOutOfMem;
while (moves != NULL) {
move = moves->next;
cuddDeallocMove(table, moves);
moves = move;
}
return(1);
ddExchangeOutOfMem:
while (moves != NULL) {
move = moves->next;
cuddDeallocMove(table, moves);
moves = move;
}
return(0);
} /* end of ddExchange */
/**Function********************************************************************
Synopsis [Moves a variable to a specified position.]
Description [If x==x_low, it executes jumping_down. If x==x_high, it
executes jumping_up. This funcion is similar to ddSiftingAux. Returns
1 in case of success; 0 otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
ddJumpingAux(
DdManager * table,
int x,
int x_low,
int x_high,
double temp)
{
Move *move;
Move *moves; /* list of moves */
int initial_size;
int result;
initial_size = table->keys - table->isolated;
#ifdef DD_DEBUG
assert(table->subtables[x].keys > 0);
#endif
moves = NULL;
if (cuddNextLow(table,x) < x_low) {
if (cuddNextHigh(table,x) > x_high) return(1);
moves = ddJumpingDown(table,x,x_high,initial_size);
/* after that point x --> x_high unless early termination */
if (moves == NULL) goto ddJumpingAuxOutOfMem;
/* move backward and stop at best position or accept uphill move */
result = siftBackwardProb(table,moves,initial_size,temp);
if (!result) goto ddJumpingAuxOutOfMem;
} else if (cuddNextHigh(table,x) > x_high) {
moves = ddJumpingUp(table,x,x_low,initial_size);
/* after that point x --> x_low unless early termination */
if (moves == NULL) goto ddJumpingAuxOutOfMem;
/* move backward and stop at best position or accept uphill move */
result = siftBackwardProb(table,moves,initial_size,temp);
if (!result) goto ddJumpingAuxOutOfMem;
} else {
(void) fprintf(table->err,"Unexpected condition in ddJumping\n");
goto ddJumpingAuxOutOfMem;
}
while (moves != NULL) {
move = moves->next;
cuddDeallocMove(table, moves);
moves = move;
}
return(1);
ddJumpingAuxOutOfMem:
while (moves != NULL) {
move = moves->next;
cuddDeallocMove(table, moves);
moves = move;
}
return(0);
} /* end of ddJumpingAux */
/**Function********************************************************************
Synopsis [This function is for jumping up.]
Description [This is a simplified version of ddSiftingUp. It does not
use lower bounding. Returns the set of moves in case of success; NULL
if memory is full.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static Move *
ddJumpingUp(
DdManager * table,
int x,
int x_low,
int initial_size)
{
Move *moves;
Move *move;
int y;
int size;
int limit_size = initial_size;
moves = NULL;
y = cuddNextLow(table,x);
while (y >= x_low) {
size = cuddSwapInPlace(table,y,x);
if (size == 0) goto ddJumpingUpOutOfMem;
move = (Move *)cuddDynamicAllocNode(table);
if (move == NULL) goto ddJumpingUpOutOfMem;
move->x = y;
move->y = x;
move->size = size;
move->next = moves;
moves = move;
if ((double) size > table->maxGrowth * (double) limit_size) {
break;
} else if (size < limit_size) {
limit_size = size;
}
x = y;
y = cuddNextLow(table,x);
}
return(moves);
ddJumpingUpOutOfMem:
while (moves != NULL) {
move = moves->next;
cuddDeallocMove(table, moves);
moves = move;
}
return(NULL);
} /* end of ddJumpingUp */
/**Function********************************************************************
Synopsis [This function is for jumping down.]
Description [This is a simplified version of ddSiftingDown. It does not
use lower bounding. Returns the set of moves in case of success; NULL
if memory is full.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static Move *
ddJumpingDown(
DdManager * table,
int x,
int x_high,
int initial_size)
{
Move *moves;
Move *move;
int y;
int size;
int limit_size = initial_size;
moves = NULL;
y = cuddNextHigh(table,x);
while (y <= x_high) {
size = cuddSwapInPlace(table,x,y);
if (size == 0) goto ddJumpingDownOutOfMem;
move = (Move *)cuddDynamicAllocNode(table);
if (move == NULL) goto ddJumpingDownOutOfMem;
move->x = x;
move->y = y;
move->size = size;
move->next = moves;
moves = move;
if ((double) size > table->maxGrowth * (double) limit_size) {
break;
} else if (size < limit_size) {
limit_size = size;
}
x = y;
y = cuddNextHigh(table,x);
}
return(moves);
ddJumpingDownOutOfMem:
while (moves != NULL) {
move = moves->next;
cuddDeallocMove(table, moves);
moves = move;
}
return(NULL);
} /* end of ddJumpingDown */
/**Function********************************************************************
Synopsis [Returns the DD to the best position encountered during
sifting if there was improvement.]
Description [Otherwise, "tosses a coin" to decide whether to keep
the current configuration or return the DD to the original
one. Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
siftBackwardProb(
DdManager * table,
Move * moves,
int size,
double temp)
{
Move *move;
int res;
int best_size = size;
double coin, threshold;
/* Look for best size during the last sifting */
for (move = moves; move != NULL; move = move->next) {
if (move->size < best_size) {
best_size = move->size;
}
}
/* If best_size equals size, the last sifting did not produce any
** improvement. We now toss a coin to decide whether to retain
** this change or not.
*/
if (best_size == size) {
coin = random_generator();
#ifdef DD_STATS
tosses++;
#endif
threshold = exp(-((double)(table->keys - table->isolated - size))/temp);
if (coin < threshold) {
#ifdef DD_STATS
acceptances++;
#endif
return(1);
}
}
/* Either there was improvement, or we have decided not to
** accept the uphill move. Go to best position.
*/
res = table->keys - table->isolated;
for (move = moves; move != NULL; move = move->next) {
if (res == best_size) return(1);
res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
if (!res) return(0);
}
return(1);
} /* end of sift_backward_prob */
/**Function********************************************************************
Synopsis [Copies the current variable order to array.]
Description [Copies the current variable order to array.
At the same time inverts the permutation.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static void
copyOrder(
DdManager * table,
int * array,
int lower,
int upper)
{
int i;
int nvars;
nvars = upper - lower + 1;
for (i = 0; i < nvars; i++) {
array[i] = table->invperm[i+lower];
}
} /* end of copyOrder */
/**Function********************************************************************
Synopsis [Restores the variable order in array by a series of sifts up.]
Description [Restores the variable order in array by a series of sifts up.
Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
restoreOrder(
DdManager * table,
int * array,
int lower,
int upper)
{
int i, x, y, size;
int nvars = upper - lower + 1;
for (i = 0; i < nvars; i++) {
x = table->perm[array[i]];
#ifdef DD_DEBUG
assert(x >= lower && x <= upper);
#endif
y = cuddNextLow(table,x);
while (y >= i + lower) {
size = cuddSwapInPlace(table,y,x);
if (size == 0) return(0);
x = y;
y = cuddNextLow(table,x);
}
}
return(1);
} /* end of restoreOrder */

979
cudd_local/cudd/cuddApa.c Normal file
View File

@@ -0,0 +1,979 @@
/**CFile***********************************************************************
FileName [cuddApa.c]
PackageName [cudd]
Synopsis [Arbitrary precision arithmetic functions.]
Description [External procedures included in this module:
<ul>
<li> Cudd_ApaNumberOfDigits()
<li> Cudd_NewApaNumber()
<li> Cudd_ApaCopy()
<li> Cudd_ApaAdd()
<li> Cudd_ApaSubtract()
<li> Cudd_ApaShortDivision()
<li> Cudd_ApaIntDivision()
<li> Cudd_ApaShiftRight()
<li> Cudd_ApaSetToLiteral()
<li> Cudd_ApaPowerOfTwo()
<li> Cudd_ApaCompare()
<li> Cudd_ApaCompareRatios()
<li> Cudd_ApaPrintHex()
<li> Cudd_ApaPrintDecimal()
<li> Cudd_ApaPrintExponential()
<li> Cudd_ApaCountMinterm()
<li> Cudd_ApaPrintMinterm()
<li> Cudd_ApaPrintMintermExp()
<li> Cudd_ApaPrintDensity()
</ul>
Static procedures included in this module:
<ul>
<li> cuddApaCountMintermAux()
<li> cuddApaStCountfree()
</ul>]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddApa.c,v 1.20 2012/02/05 01:07:18 fabio Exp $";
#endif
static DdNode *background, *zero;
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static DdApaNumber cuddApaCountMintermAux (DdNode * node, int digits, DdApaNumber max, DdApaNumber min, st_table * table);
static enum st_retval cuddApaStCountfree (char * key, char * value, char * arg);
/**AutomaticEnd***************************************************************/
#ifdef __cplusplus
} /* end of extern "C" */
#endif
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Finds the number of digits for an arbitrary precision
integer.]
Description [Finds the number of digits for an arbitrary precision
integer given the maximum number of binary digits. The number of
binary digits should be positive. Returns the number of digits if
successful; 0 otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
int
Cudd_ApaNumberOfDigits(
int binaryDigits)
{
int digits;
digits = binaryDigits / DD_APA_BITS;
if ((digits * DD_APA_BITS) != binaryDigits)
digits++;
return(digits);
} /* end of Cudd_ApaNumberOfDigits */
/**Function********************************************************************
Synopsis [Allocates memory for an arbitrary precision integer.]
Description [Allocates memory for an arbitrary precision
integer. Returns a pointer to the allocated memory if successful;
NULL otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
DdApaNumber
Cudd_NewApaNumber(
int digits)
{
return(ALLOC(DdApaDigit, digits));
} /* end of Cudd_NewApaNumber */
/**Function********************************************************************
Synopsis [Makes a copy of an arbitrary precision integer.]
Description [Makes a copy of an arbitrary precision integer.]
SideEffects [Changes parameter <code>dest</code>.]
SeeAlso []
******************************************************************************/
void
Cudd_ApaCopy(
int digits,
DdApaNumber source,
DdApaNumber dest)
{
int i;
for (i = 0; i < digits; i++) {
dest[i] = source[i];
}
} /* end of Cudd_ApaCopy */
/**Function********************************************************************
Synopsis [Adds two arbitrary precision integers.]
Description [Adds two arbitrary precision integers. Returns the
carry out of the most significant digit.]
SideEffects [The result of the sum is stored in parameter <code>sum</code>.]
SeeAlso []
******************************************************************************/
DdApaDigit
Cudd_ApaAdd(
int digits,
DdApaNumber a,
DdApaNumber b,
DdApaNumber sum)
{
int i;
DdApaDoubleDigit partial = 0;
for (i = digits - 1; i >= 0; i--) {
partial = a[i] + b[i] + DD_MSDIGIT(partial);
sum[i] = (DdApaDigit) DD_LSDIGIT(partial);
}
return((DdApaDigit) DD_MSDIGIT(partial));
} /* end of Cudd_ApaAdd */
/**Function********************************************************************
Synopsis [Subtracts two arbitrary precision integers.]
Description [Subtracts two arbitrary precision integers. Returns the
borrow out of the most significant digit.]
SideEffects [The result of the subtraction is stored in parameter
<code>diff</code>.]
SeeAlso []
******************************************************************************/
DdApaDigit
Cudd_ApaSubtract(
int digits,
DdApaNumber a,
DdApaNumber b,
DdApaNumber diff)
{
int i;
DdApaDoubleDigit partial = DD_APA_BASE;
for (i = digits - 1; i >= 0; i--) {
partial = DD_MSDIGIT(partial) + DD_APA_MASK + a[i] - b[i];
diff[i] = (DdApaDigit) DD_LSDIGIT(partial);
}
return((DdApaDigit) DD_MSDIGIT(partial) - 1);
} /* end of Cudd_ApaSubtract */
/**Function********************************************************************
Synopsis [Divides an arbitrary precision integer by a digit.]
Description [Divides an arbitrary precision integer by a digit.]
SideEffects [The quotient is returned in parameter <code>quotient</code>.]
SeeAlso []
******************************************************************************/
DdApaDigit
Cudd_ApaShortDivision(
int digits,
DdApaNumber dividend,
DdApaDigit divisor,
DdApaNumber quotient)
{
int i;
DdApaDigit remainder;
DdApaDoubleDigit partial;
remainder = 0;
for (i = 0; i < digits; i++) {
partial = remainder * DD_APA_BASE + dividend[i];
quotient[i] = (DdApaDigit) (partial/(DdApaDoubleDigit)divisor);
remainder = (DdApaDigit) (partial % divisor);
}
return(remainder);
} /* end of Cudd_ApaShortDivision */
/**Function********************************************************************
Synopsis [Divides an arbitrary precision integer by an integer.]
Description [Divides an arbitrary precision integer by a 32-bit
unsigned integer. Returns the remainder of the division. This
procedure relies on the assumption that the number of bits of a
DdApaDigit plus the number of bits of an unsigned int is less the
number of bits of the mantissa of a double. This guarantees that the
product of a DdApaDigit and an unsigned int can be represented
without loss of precision by a double. On machines where this
assumption is not satisfied, this procedure will malfunction.]
SideEffects [The quotient is returned in parameter <code>quotient</code>.]
SeeAlso [Cudd_ApaShortDivision]
******************************************************************************/
unsigned int
Cudd_ApaIntDivision(
int digits,
DdApaNumber dividend,
unsigned int divisor,
DdApaNumber quotient)
{
int i;
double partial;
unsigned int remainder = 0;
double ddiv = (double) divisor;
for (i = 0; i < digits; i++) {
partial = (double) remainder * DD_APA_BASE + dividend[i];
quotient[i] = (DdApaDigit) (partial / ddiv);
remainder = (unsigned int) (partial - ((double)quotient[i] * ddiv));
}
return(remainder);
} /* end of Cudd_ApaIntDivision */
/**Function********************************************************************
Synopsis [Shifts right an arbitrary precision integer by one binary
place.]
Description [Shifts right an arbitrary precision integer by one
binary place. The most significant binary digit of the result is
taken from parameter <code>in</code>.]
SideEffects [The result is returned in parameter <code>b</code>.]
SeeAlso []
******************************************************************************/
void
Cudd_ApaShiftRight(
int digits,
DdApaDigit in,
DdApaNumber a,
DdApaNumber b)
{
int i;
for (i = digits - 1; i > 0; i--) {
b[i] = (a[i] >> 1) | ((a[i-1] & 1) << (DD_APA_BITS - 1));
}
b[0] = (a[0] >> 1) | (in << (DD_APA_BITS - 1));
} /* end of Cudd_ApaShiftRight */
/**Function********************************************************************
Synopsis [Sets an arbitrary precision integer to a one-digit literal.]
Description [Sets an arbitrary precision integer to a one-digit literal.]
SideEffects [The result is returned in parameter <code>number</code>.]
SeeAlso []
******************************************************************************/
void
Cudd_ApaSetToLiteral(
int digits,
DdApaNumber number,
DdApaDigit literal)
{
int i;
for (i = 0; i < digits - 1; i++)
number[i] = 0;
number[digits - 1] = literal;
} /* end of Cudd_ApaSetToLiteral */
/**Function********************************************************************
Synopsis [Sets an arbitrary precision integer to a power of two.]
Description [Sets an arbitrary precision integer to a power of
two. If the power of two is too large to be represented, the number
is set to 0.]
SideEffects [The result is returned in parameter <code>number</code>.]
SeeAlso []
******************************************************************************/
void
Cudd_ApaPowerOfTwo(
int digits,
DdApaNumber number,
int power)
{
int i;
int index;
for (i = 0; i < digits; i++)
number[i] = 0;
i = digits - 1 - power / DD_APA_BITS;
if (i < 0) return;
index = power & (DD_APA_BITS - 1);
number[i] = 1 << index;
} /* end of Cudd_ApaPowerOfTwo */
/**Function********************************************************************
Synopsis [Compares two arbitrary precision integers.]
Description [Compares two arbitrary precision integers. Returns 1 if
the first number is larger; 0 if they are equal; -1 if the second
number is larger.]
SideEffects [None]
SeeAlso []
******************************************************************************/
int
Cudd_ApaCompare(
int digitsFirst,
DdApaNumber first,
int digitsSecond,
DdApaNumber second)
{
int i;
int firstNZ, secondNZ;
/* Find first non-zero in both numbers. */
for (firstNZ = 0; firstNZ < digitsFirst; firstNZ++)
if (first[firstNZ] != 0) break;
for (secondNZ = 0; secondNZ < digitsSecond; secondNZ++)
if (second[secondNZ] != 0) break;
if (digitsFirst - firstNZ > digitsSecond - secondNZ) return(1);
else if (digitsFirst - firstNZ < digitsSecond - secondNZ) return(-1);
for (i = 0; i < digitsFirst - firstNZ; i++) {
if (first[firstNZ + i] > second[secondNZ + i]) return(1);
else if (first[firstNZ + i] < second[secondNZ + i]) return(-1);
}
return(0);
} /* end of Cudd_ApaCompare */
/**Function********************************************************************
Synopsis [Compares the ratios of two arbitrary precision integers to two
unsigned ints.]
Description [Compares the ratios of two arbitrary precision integers
to two unsigned ints. Returns 1 if the first number is larger; 0 if
they are equal; -1 if the second number is larger.]
SideEffects [None]
SeeAlso []
******************************************************************************/
int
Cudd_ApaCompareRatios(
int digitsFirst,
DdApaNumber firstNum,
unsigned int firstDen,
int digitsSecond,
DdApaNumber secondNum,
unsigned int secondDen)
{
int result;
DdApaNumber first, second;
unsigned int firstRem, secondRem;
first = Cudd_NewApaNumber(digitsFirst);
firstRem = Cudd_ApaIntDivision(digitsFirst,firstNum,firstDen,first);
second = Cudd_NewApaNumber(digitsSecond);
secondRem = Cudd_ApaIntDivision(digitsSecond,secondNum,secondDen,second);
result = Cudd_ApaCompare(digitsFirst,first,digitsSecond,second);
FREE(first);
FREE(second);
if (result == 0) {
if ((double)firstRem/firstDen > (double)secondRem/secondDen)
return(1);
else if ((double)firstRem/firstDen < (double)secondRem/secondDen)
return(-1);
}
return(result);
} /* end of Cudd_ApaCompareRatios */
/**Function********************************************************************
Synopsis [Prints an arbitrary precision integer in hexadecimal format.]
Description [Prints an arbitrary precision integer in hexadecimal format.
Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [Cudd_ApaPrintDecimal Cudd_ApaPrintExponential]
******************************************************************************/
int
Cudd_ApaPrintHex(
FILE * fp,
int digits,
DdApaNumber number)
{
int i, result;
for (i = 0; i < digits; i++) {
result = fprintf(fp,DD_APA_HEXPRINT,number[i]);
if (result == EOF)
return(0);
}
return(1);
} /* end of Cudd_ApaPrintHex */
/**Function********************************************************************
Synopsis [Prints an arbitrary precision integer in decimal format.]
Description [Prints an arbitrary precision integer in decimal format.
Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [Cudd_ApaPrintHex Cudd_ApaPrintExponential]
******************************************************************************/
int
Cudd_ApaPrintDecimal(
FILE * fp,
int digits,
DdApaNumber number)
{
int i, result;
DdApaDigit remainder;
DdApaNumber work;
unsigned char *decimal;
int leadingzero;
int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1;
work = Cudd_NewApaNumber(digits);
if (work == NULL)
return(0);
decimal = ALLOC(unsigned char, decimalDigits);
if (decimal == NULL) {
FREE(work);
return(0);
}
Cudd_ApaCopy(digits,number,work);
for (i = decimalDigits - 1; i >= 0; i--) {
remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work);
decimal[i] = (unsigned char) remainder;
}
FREE(work);
leadingzero = 1;
for (i = 0; i < decimalDigits; i++) {
leadingzero = leadingzero && (decimal[i] == 0);
if ((!leadingzero) || (i == (decimalDigits - 1))) {
result = fprintf(fp,"%1d",decimal[i]);
if (result == EOF) {
FREE(decimal);
return(0);
}
}
}
FREE(decimal);
return(1);
} /* end of Cudd_ApaPrintDecimal */
/**Function********************************************************************
Synopsis [Prints an arbitrary precision integer in exponential format.]
Description [Prints an arbitrary precision integer in exponential format.
Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [Cudd_ApaPrintHex Cudd_ApaPrintDecimal]
******************************************************************************/
int
Cudd_ApaPrintExponential(
FILE * fp,
int digits,
DdApaNumber number,
int precision)
{
int i, first, last, result;
DdApaDigit remainder;
DdApaNumber work;
unsigned char *decimal;
int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1;
work = Cudd_NewApaNumber(digits);
if (work == NULL)
return(0);
decimal = ALLOC(unsigned char, decimalDigits);
if (decimal == NULL) {
FREE(work);
return(0);
}
Cudd_ApaCopy(digits,number,work);
first = decimalDigits - 1;
for (i = decimalDigits - 1; i >= 0; i--) {
remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work);
decimal[i] = (unsigned char) remainder;
if (remainder != 0) first = i; /* keep track of MS non-zero */
}
FREE(work);
last = ddMin(first + precision, decimalDigits);
for (i = first; i < last; i++) {
result = fprintf(fp,"%s%1d",i == first+1 ? "." : "", decimal[i]);
if (result == EOF) {
FREE(decimal);
return(0);
}
}
FREE(decimal);
result = fprintf(fp,"e+%d",decimalDigits - first - 1);
if (result == EOF) {
return(0);
}
return(1);
} /* end of Cudd_ApaPrintExponential */
/**Function********************************************************************
Synopsis [Counts the number of minterms of a DD.]
Description [Counts the number of minterms of a DD. The function is
assumed to depend on nvars variables. The minterm count is
represented as an arbitrary precision unsigned integer, to allow for
any number of variables CUDD supports. Returns a pointer to the
array representing the number of minterms of the function rooted at
node if successful; NULL otherwise.]
SideEffects [The number of digits of the result is returned in
parameter <code>digits</code>.]
SeeAlso [Cudd_CountMinterm]
******************************************************************************/
DdApaNumber
Cudd_ApaCountMinterm(
DdManager * manager,
DdNode * node,
int nvars,
int * digits)
{
DdApaNumber max, min;
st_table *table;
DdApaNumber i,count;
background = manager->background;
zero = Cudd_Not(manager->one);
*digits = Cudd_ApaNumberOfDigits(nvars+1);
max = Cudd_NewApaNumber(*digits);
if (max == NULL) {
return(NULL);
}
Cudd_ApaPowerOfTwo(*digits,max,nvars);
min = Cudd_NewApaNumber(*digits);
if (min == NULL) {
FREE(max);
return(NULL);
}
Cudd_ApaSetToLiteral(*digits,min,0);
table = st_init_table(st_ptrcmp,st_ptrhash);
if (table == NULL) {
FREE(max);
FREE(min);
return(NULL);
}
i = cuddApaCountMintermAux(Cudd_Regular(node),*digits,max,min,table);
if (i == NULL) {
FREE(max);
FREE(min);
st_foreach(table, cuddApaStCountfree, NULL);
st_free_table(table);
return(NULL);
}
count = Cudd_NewApaNumber(*digits);
if (count == NULL) {
FREE(max);
FREE(min);
st_foreach(table, cuddApaStCountfree, NULL);
st_free_table(table);
if (Cudd_Regular(node)->ref == 1) FREE(i);
return(NULL);
}
if (Cudd_IsComplement(node)) {
(void) Cudd_ApaSubtract(*digits,max,i,count);
} else {
Cudd_ApaCopy(*digits,i,count);
}
FREE(max);
FREE(min);
st_foreach(table, cuddApaStCountfree, NULL);
st_free_table(table);
if (Cudd_Regular(node)->ref == 1) FREE(i);
return(count);
} /* end of Cudd_ApaCountMinterm */
/**Function********************************************************************
Synopsis [Prints the number of minterms of a BDD or ADD using
arbitrary precision arithmetic.]
Description [Prints the number of minterms of a BDD or ADD using
arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [Cudd_ApaPrintMintermExp]
******************************************************************************/
int
Cudd_ApaPrintMinterm(
FILE * fp,
DdManager * dd,
DdNode * node,
int nvars)
{
int digits;
int result;
DdApaNumber count;
count = Cudd_ApaCountMinterm(dd,node,nvars,&digits);
if (count == NULL)
return(0);
result = Cudd_ApaPrintDecimal(fp,digits,count);
FREE(count);
if (fprintf(fp,"\n") == EOF) {
return(0);
}
return(result);
} /* end of Cudd_ApaPrintMinterm */
/**Function********************************************************************
Synopsis [Prints the number of minterms of a BDD or ADD in exponential
format using arbitrary precision arithmetic.]
Description [Prints the number of minterms of a BDD or ADD in
exponential format using arbitrary precision arithmetic. Parameter
precision controls the number of signficant digits printed. Returns
1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [Cudd_ApaPrintMinterm]
******************************************************************************/
int
Cudd_ApaPrintMintermExp(
FILE * fp,
DdManager * dd,
DdNode * node,
int nvars,
int precision)
{
int digits;
int result;
DdApaNumber count;
count = Cudd_ApaCountMinterm(dd,node,nvars,&digits);
if (count == NULL)
return(0);
result = Cudd_ApaPrintExponential(fp,digits,count,precision);
FREE(count);
if (fprintf(fp,"\n") == EOF) {
return(0);
}
return(result);
} /* end of Cudd_ApaPrintMintermExp */
/**Function********************************************************************
Synopsis [Prints the density of a BDD or ADD using
arbitrary precision arithmetic.]
Description [Prints the density of a BDD or ADD using
arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
int
Cudd_ApaPrintDensity(
FILE * fp,
DdManager * dd,
DdNode * node,
int nvars)
{
int digits;
int result;
DdApaNumber count,density;
unsigned int size, remainder, fractional;
count = Cudd_ApaCountMinterm(dd,node,nvars,&digits);
if (count == NULL)
return(0);
size = Cudd_DagSize(node);
density = Cudd_NewApaNumber(digits);
remainder = Cudd_ApaIntDivision(digits,count,size,density);
result = Cudd_ApaPrintDecimal(fp,digits,density);
FREE(count);
FREE(density);
fractional = (unsigned int)((double)remainder / size * 1000000);
if (fprintf(fp,".%u\n", fractional) == EOF) {
return(0);
}
return(result);
} /* end of Cudd_ApaPrintDensity */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_ApaCountMinterm.]
Description [Performs the recursive step of Cudd_ApaCountMinterm.
It is based on the following identity. Let |f| be the
number of minterms of f. Then:
<xmp>
|f| = (|f0|+|f1|)/2
</xmp>
where f0 and f1 are the two cofactors of f.
Uses the identity <code>|f'| = max - |f|</code>.
The procedure expects the argument "node" to be a regular pointer, and
guarantees this condition is met in the recursive calls.
For efficiency, the result of a call is cached only if the node has
a reference count greater than 1.
Returns the number of minterms of the function rooted at node.]
SideEffects [None]
******************************************************************************/
static DdApaNumber
cuddApaCountMintermAux(
DdNode * node,
int digits,
DdApaNumber max,
DdApaNumber min,
st_table * table)
{
DdNode *Nt, *Ne;
DdApaNumber mint, mint1, mint2;
DdApaDigit carryout;
if (cuddIsConstant(node)) {
if (node == background || node == zero) {
return(min);
} else {
return(max);
}
}
if (node->ref > 1 && st_lookup(table, node, &mint)) {
return(mint);
}
Nt = cuddT(node); Ne = cuddE(node);
mint1 = cuddApaCountMintermAux(Nt, digits, max, min, table);
if (mint1 == NULL) return(NULL);
mint2 = cuddApaCountMintermAux(Cudd_Regular(Ne), digits, max, min, table);
if (mint2 == NULL) {
if (Nt->ref == 1) FREE(mint1);
return(NULL);
}
mint = Cudd_NewApaNumber(digits);
if (mint == NULL) {
if (Nt->ref == 1) FREE(mint1);
if (Cudd_Regular(Ne)->ref == 1) FREE(mint2);
return(NULL);
}
if (Cudd_IsComplement(Ne)) {
(void) Cudd_ApaSubtract(digits,max,mint2,mint);
carryout = Cudd_ApaAdd(digits,mint1,mint,mint);
} else {
carryout = Cudd_ApaAdd(digits,mint1,mint2,mint);
}
Cudd_ApaShiftRight(digits,carryout,mint,mint);
/* If the refernce count of a child is 1, its minterm count
** hasn't been stored in table. Therefore, it must be explicitly
** freed here. */
if (Nt->ref == 1) FREE(mint1);
if (Cudd_Regular(Ne)->ref == 1) FREE(mint2);
if (node->ref > 1) {
if (st_insert(table, (char *)node, (char *)mint) == ST_OUT_OF_MEM) {
FREE(mint);
return(NULL);
}
}
return(mint);
} /* end of cuddApaCountMintermAux */
/**Function********************************************************************
Synopsis [Frees the memory used to store the minterm counts recorded
in the visited table.]
Description [Frees the memory used to store the minterm counts
recorded in the visited table. Returns ST_CONTINUE.]
SideEffects [None]
******************************************************************************/
static enum st_retval
cuddApaStCountfree(
char * key,
char * value,
char * arg)
{
DdApaNumber d;
d = (DdApaNumber) value;
FREE(d);
return(ST_CONTINUE);
} /* end of cuddApaStCountfree */

2204
cudd_local/cudd/cuddApprox.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,760 @@
/**CFile***********************************************************************
FileName [cuddBddAbs.c]
PackageName [cudd]
Synopsis [Quantification functions for BDDs.]
Description [External procedures included in this module:
<ul>
<li> Cudd_bddExistAbstract()
<li> Cudd_bddExistAbstractLimit()
<li> Cudd_bddXorExistAbstract()
<li> Cudd_bddUnivAbstract()
<li> Cudd_bddBooleanDiff()
<li> Cudd_bddVarIsDependent()
</ul>
Internal procedures included in this module:
<ul>
<li> cuddBddExistAbstractRecur()
<li> cuddBddXorExistAbstractRecur()
<li> cuddBddBooleanDiffRecur()
</ul>
Static procedures included in this module:
<ul>
<li> bddCheckPositiveCube()
</ul>
]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddBddAbs.c,v 1.28 2012/02/05 01:07:18 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static int bddCheckPositiveCube (DdManager *manager, DdNode *cube);
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Existentially abstracts all the variables in cube from f.]
Description [Existentially abstracts all the variables in cube from f.
Returns the abstracted BDD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddUnivAbstract Cudd_addExistAbstract]
******************************************************************************/
DdNode *
Cudd_bddExistAbstract(
DdManager * manager,
DdNode * f,
DdNode * cube)
{
DdNode *res;
if (bddCheckPositiveCube(manager, cube) == 0) {
(void) fprintf(manager->err,
"Error: Can only abstract positive cubes\n");
manager->errorCode = CUDD_INVALID_ARG;
return(NULL);
}
do {
manager->reordered = 0;
res = cuddBddExistAbstractRecur(manager, f, cube);
} while (manager->reordered == 1);
return(res);
} /* end of Cudd_bddExistAbstract */
/**Function********************************************************************
Synopsis [Existentially abstracts all the variables in cube from f.]
Description [Existentially abstracts all the variables in cube from f.
Returns the abstracted BDD if successful; NULL if the intermediate
result blows up or more new nodes than <code>limit</code> are
required.]
SideEffects [None]
SeeAlso [Cudd_bddExistAbstract]
******************************************************************************/
DdNode *
Cudd_bddExistAbstractLimit(
DdManager * manager,
DdNode * f,
DdNode * cube,
unsigned int limit)
{
DdNode *res;
unsigned int saveLimit = manager->maxLive;
if (bddCheckPositiveCube(manager, cube) == 0) {
(void) fprintf(manager->err,
"Error: Can only abstract positive cubes\n");
manager->errorCode = CUDD_INVALID_ARG;
return(NULL);
}
manager->maxLive = (manager->keys - manager->dead) +
(manager->keysZ - manager->deadZ) + limit;
do {
manager->reordered = 0;
res = cuddBddExistAbstractRecur(manager, f, cube);
} while (manager->reordered == 1);
manager->maxLive = saveLimit;
return(res);
} /* end of Cudd_bddExistAbstractLimit */
/**Function********************************************************************
Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the
variables in cube.]
Description [Takes the exclusive OR of two BDDs and simultaneously abstracts
the variables in cube. The variables are existentially abstracted. Returns a
pointer to the result is successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddUnivAbstract Cudd_bddExistAbstract Cudd_bddAndAbstract]
******************************************************************************/
DdNode *
Cudd_bddXorExistAbstract(
DdManager * manager,
DdNode * f,
DdNode * g,
DdNode * cube)
{
DdNode *res;
if (bddCheckPositiveCube(manager, cube) == 0) {
(void) fprintf(manager->err,
"Error: Can only abstract positive cubes\n");
manager->errorCode = CUDD_INVALID_ARG;
return(NULL);
}
do {
manager->reordered = 0;
res = cuddBddXorExistAbstractRecur(manager, f, g, cube);
} while (manager->reordered == 1);
return(res);
} /* end of Cudd_bddXorExistAbstract */
/**Function********************************************************************
Synopsis [Universally abstracts all the variables in cube from f.]
Description [Universally abstracts all the variables in cube from f.
Returns the abstracted BDD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddExistAbstract Cudd_addUnivAbstract]
******************************************************************************/
DdNode *
Cudd_bddUnivAbstract(
DdManager * manager,
DdNode * f,
DdNode * cube)
{
DdNode *res;
if (bddCheckPositiveCube(manager, cube) == 0) {
(void) fprintf(manager->err,
"Error: Can only abstract positive cubes\n");
manager->errorCode = CUDD_INVALID_ARG;
return(NULL);
}
do {
manager->reordered = 0;
res = cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube);
} while (manager->reordered == 1);
if (res != NULL) res = Cudd_Not(res);
return(res);
} /* end of Cudd_bddUnivAbstract */
/**Function********************************************************************
Synopsis [Computes the boolean difference of f with respect to x.]
Description [Computes the boolean difference of f with respect to the
variable with index x. Returns the BDD of the boolean difference if
successful; NULL otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
DdNode *
Cudd_bddBooleanDiff(
DdManager * manager,
DdNode * f,
int x)
{
DdNode *res, *var;
/* If the variable is not currently in the manager, f cannot
** depend on it.
*/
if (x >= manager->size) return(Cudd_Not(DD_ONE(manager)));
var = manager->vars[x];
do {
manager->reordered = 0;
res = cuddBddBooleanDiffRecur(manager, Cudd_Regular(f), var);
} while (manager->reordered == 1);
return(res);
} /* end of Cudd_bddBooleanDiff */
/**Function********************************************************************
Synopsis [Checks whether a variable is dependent on others in a
function.]
Description [Checks whether a variable is dependent on others in a
function. Returns 1 if the variable is dependent; 0 otherwise. No
new nodes are created.]
SideEffects [None]
SeeAlso []
******************************************************************************/
int
Cudd_bddVarIsDependent(
DdManager *dd, /* manager */
DdNode *f, /* function */
DdNode *var /* variable */)
{
DdNode *F, *res, *zero, *ft, *fe;
unsigned topf, level;
DD_CTFP cacheOp;
int retval;
zero = Cudd_Not(DD_ONE(dd));
if (Cudd_IsConstant(f)) return(f == zero);
/* From now on f is not constant. */
F = Cudd_Regular(f);
topf = (unsigned) dd->perm[F->index];
level = (unsigned) dd->perm[var->index];
/* Check terminal case. If topf > index of var, f does not depend on var.
** Therefore, var is not dependent in f. */
if (topf > level) {
return(0);
}
cacheOp = (DD_CTFP) Cudd_bddVarIsDependent;
res = cuddCacheLookup2(dd,cacheOp,f,var);
if (res != NULL) {
return(res != zero);
}
/* Compute cofactors. */
ft = Cudd_NotCond(cuddT(F), f != F);
fe = Cudd_NotCond(cuddE(F), f != F);
if (topf == level) {
retval = Cudd_bddLeq(dd,ft,Cudd_Not(fe));
} else {
retval = Cudd_bddVarIsDependent(dd,ft,var) &&
Cudd_bddVarIsDependent(dd,fe,var);
}
cuddCacheInsert2(dd,cacheOp,f,var,Cudd_NotCond(zero,retval));
return(retval);
} /* Cudd_bddVarIsDependent */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Performs the recursive steps of Cudd_bddExistAbstract.]
Description [Performs the recursive steps of Cudd_bddExistAbstract.
Returns the BDD obtained by abstracting the variables
of cube from f if successful; NULL otherwise. It is also used by
Cudd_bddUnivAbstract.]
SideEffects [None]
SeeAlso [Cudd_bddExistAbstract Cudd_bddUnivAbstract]
******************************************************************************/
DdNode *
cuddBddExistAbstractRecur(
DdManager * manager,
DdNode * f,
DdNode * cube)
{
DdNode *F, *T, *E, *res, *res1, *res2, *one;
statLine(manager);
one = DD_ONE(manager);
F = Cudd_Regular(f);
/* Cube is guaranteed to be a cube at this point. */
if (cube == one || F == one) {
return(f);
}
/* From now on, f and cube are non-constant. */
/* Abstract a variable that does not appear in f. */
while (manager->perm[F->index] > manager->perm[cube->index]) {
cube = cuddT(cube);
if (cube == one) return(f);
}
/* Check the cache. */
if (F->ref != 1 && (res = cuddCacheLookup2(manager, Cudd_bddExistAbstract, f, cube)) != NULL) {
return(res);
}
/* Compute the cofactors of f. */
T = cuddT(F); E = cuddE(F);
if (f != F) {
T = Cudd_Not(T); E = Cudd_Not(E);
}
/* If the two indices are the same, so are their levels. */
if (F->index == cube->index) {
if (T == one || E == one || T == Cudd_Not(E)) {
return(one);
}
res1 = cuddBddExistAbstractRecur(manager, T, cuddT(cube));
if (res1 == NULL) return(NULL);
if (res1 == one) {
if (F->ref != 1)
cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, one);
return(one);
}
cuddRef(res1);
res2 = cuddBddExistAbstractRecur(manager, E, cuddT(cube));
if (res2 == NULL) {
Cudd_IterDerefBdd(manager,res1);
return(NULL);
}
cuddRef(res2);
res = cuddBddAndRecur(manager, Cudd_Not(res1), Cudd_Not(res2));
if (res == NULL) {
Cudd_IterDerefBdd(manager, res1);
Cudd_IterDerefBdd(manager, res2);
return(NULL);
}
res = Cudd_Not(res);
cuddRef(res);
Cudd_IterDerefBdd(manager, res1);
Cudd_IterDerefBdd(manager, res2);
if (F->ref != 1)
cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res);
cuddDeref(res);
return(res);
} else { /* if (cuddI(manager,F->index) < cuddI(manager,cube->index)) */
res1 = cuddBddExistAbstractRecur(manager, T, cube);
if (res1 == NULL) return(NULL);
cuddRef(res1);
res2 = cuddBddExistAbstractRecur(manager, E, cube);
if (res2 == NULL) {
Cudd_IterDerefBdd(manager, res1);
return(NULL);
}
cuddRef(res2);
/* ITE takes care of possible complementation of res1 and of the
** case in which res1 == res2. */
res = cuddBddIteRecur(manager, manager->vars[F->index], res1, res2);
if (res == NULL) {
Cudd_IterDerefBdd(manager, res1);
Cudd_IterDerefBdd(manager, res2);
return(NULL);
}
cuddDeref(res1);
cuddDeref(res2);
if (F->ref != 1)
cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res);
return(res);
}
} /* end of cuddBddExistAbstractRecur */
/**Function********************************************************************
Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the
variables in cube.]
Description [Takes the exclusive OR of two BDDs and simultaneously abstracts
the variables in cube. The variables are existentially abstracted. Returns a
pointer to the result is successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddAndAbstract]
******************************************************************************/
DdNode *
cuddBddXorExistAbstractRecur(
DdManager * manager,
DdNode * f,
DdNode * g,
DdNode * cube)
{
DdNode *F, *fv, *fnv, *G, *gv, *gnv;
DdNode *one, *zero, *r, *t, *e, *Cube;
unsigned int topf, topg, topcube, top, index;
statLine(manager);
one = DD_ONE(manager);
zero = Cudd_Not(one);
/* Terminal cases. */
if (f == g) {
return(zero);
}
if (f == Cudd_Not(g)) {
return(one);
}
if (cube == one) {
return(cuddBddXorRecur(manager, f, g));
}
if (f == one) {
return(cuddBddExistAbstractRecur(manager, Cudd_Not(g), cube));
}
if (g == one) {
return(cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube));
}
if (f == zero) {
return(cuddBddExistAbstractRecur(manager, g, cube));
}
if (g == zero) {
return(cuddBddExistAbstractRecur(manager, f, cube));
}
/* At this point f, g, and cube are not constant. */
if (f > g) { /* Try to increase cache efficiency. */
DdNode *tmp = f;
f = g;
g = tmp;
}
/* Check cache. */
r = cuddCacheLookup(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube);
if (r != NULL) {
return(r);
}
/* Here we can skip the use of cuddI, because the operands are known
** to be non-constant.
*/
F = Cudd_Regular(f);
topf = manager->perm[F->index];
G = Cudd_Regular(g);
topg = manager->perm[G->index];
top = ddMin(topf, topg);
topcube = manager->perm[cube->index];
if (topcube < top) {
return(cuddBddXorExistAbstractRecur(manager, f, g, cuddT(cube)));
}
/* Now, topcube >= top. */
if (topf == top) {
index = F->index;
fv = cuddT(F);
fnv = cuddE(F);
if (Cudd_IsComplement(f)) {
fv = Cudd_Not(fv);
fnv = Cudd_Not(fnv);
}
} else {
index = G->index;
fv = fnv = f;
}
if (topg == top) {
gv = cuddT(G);
gnv = cuddE(G);
if (Cudd_IsComplement(g)) {
gv = Cudd_Not(gv);
gnv = Cudd_Not(gnv);
}
} else {
gv = gnv = g;
}
if (topcube == top) {
Cube = cuddT(cube);
} else {
Cube = cube;
}
t = cuddBddXorExistAbstractRecur(manager, fv, gv, Cube);
if (t == NULL) return(NULL);
/* Special case: 1 OR anything = 1. Hence, no need to compute
** the else branch if t is 1.
*/
if (t == one && topcube == top) {
cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, one);
return(one);
}
cuddRef(t);
e = cuddBddXorExistAbstractRecur(manager, fnv, gnv, Cube);
if (e == NULL) {
Cudd_IterDerefBdd(manager, t);
return(NULL);
}
cuddRef(e);
if (topcube == top) { /* abstract */
r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e));
if (r == NULL) {
Cudd_IterDerefBdd(manager, t);
Cudd_IterDerefBdd(manager, e);
return(NULL);
}
r = Cudd_Not(r);
cuddRef(r);
Cudd_IterDerefBdd(manager, t);
Cudd_IterDerefBdd(manager, e);
cuddDeref(r);
} else if (t == e) {
r = t;
cuddDeref(t);
cuddDeref(e);
} else {
if (Cudd_IsComplement(t)) {
r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
if (r == NULL) {
Cudd_IterDerefBdd(manager, t);
Cudd_IterDerefBdd(manager, e);
return(NULL);
}
r = Cudd_Not(r);
} else {
r = cuddUniqueInter(manager,(int)index,t,e);
if (r == NULL) {
Cudd_IterDerefBdd(manager, t);
Cudd_IterDerefBdd(manager, e);
return(NULL);
}
}
cuddDeref(e);
cuddDeref(t);
}
cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, r);
return (r);
} /* end of cuddBddXorExistAbstractRecur */
/**Function********************************************************************
Synopsis [Performs the recursive steps of Cudd_bddBoleanDiff.]
Description [Performs the recursive steps of Cudd_bddBoleanDiff.
Returns the BDD obtained by XORing the cofactors of f with respect to
var if successful; NULL otherwise. Exploits the fact that dF/dx =
dF'/dx.]
SideEffects [None]
SeeAlso []
******************************************************************************/
DdNode *
cuddBddBooleanDiffRecur(
DdManager * manager,
DdNode * f,
DdNode * var)
{
DdNode *T, *E, *res, *res1, *res2;
statLine(manager);
if (cuddI(manager,f->index) > manager->perm[var->index]) {
/* f does not depend on var. */
return(Cudd_Not(DD_ONE(manager)));
}
/* From now on, f is non-constant. */
/* If the two indices are the same, so are their levels. */
if (f->index == var->index) {
res = cuddBddXorRecur(manager, cuddT(f), cuddE(f));
return(res);
}
/* From now on, cuddI(manager,f->index) < cuddI(manager,cube->index). */
/* Check the cache. */
res = cuddCacheLookup2(manager, cuddBddBooleanDiffRecur, f, var);
if (res != NULL) {
return(res);
}
/* Compute the cofactors of f. */
T = cuddT(f); E = cuddE(f);
res1 = cuddBddBooleanDiffRecur(manager, T, var);
if (res1 == NULL) return(NULL);
cuddRef(res1);
res2 = cuddBddBooleanDiffRecur(manager, Cudd_Regular(E), var);
if (res2 == NULL) {
Cudd_IterDerefBdd(manager, res1);
return(NULL);
}
cuddRef(res2);
/* ITE takes care of possible complementation of res1 and of the
** case in which res1 == res2. */
res = cuddBddIteRecur(manager, manager->vars[f->index], res1, res2);
if (res == NULL) {
Cudd_IterDerefBdd(manager, res1);
Cudd_IterDerefBdd(manager, res2);
return(NULL);
}
cuddDeref(res1);
cuddDeref(res2);
cuddCacheInsert2(manager, cuddBddBooleanDiffRecur, f, var, res);
return(res);
} /* end of cuddBddBooleanDiffRecur */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Checks whether cube is an BDD representing the product of
positive literals.]
Description [Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
******************************************************************************/
static int
bddCheckPositiveCube(
DdManager * manager,
DdNode * cube)
{
if (Cudd_IsComplement(cube)) return(0);
if (cube == DD_ONE(manager)) return(1);
if (cuddIsConstant(cube)) return(0);
if (cuddE(cube) == Cudd_Not(DD_ONE(manager))) {
return(bddCheckPositiveCube(manager, cuddT(cube)));
}
return(0);
} /* end of bddCheckPositiveCube */

View File

@@ -0,0 +1,515 @@
/**CFile***********************************************************************
FileName [cuddBddCorr.c]
PackageName [cudd]
Synopsis [Correlation between BDDs.]
Description [External procedures included in this module:
<ul>
<li> Cudd_bddCorrelation()
<li> Cudd_bddCorrelationWeights()
</ul>
Static procedures included in this module:
<ul>
<li> bddCorrelationAux()
<li> bddCorrelationWeightsAux()
<li> CorrelCompare()
<li> CorrelHash()
<li> CorrelCleanUp()
</ul>
]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
typedef struct hashEntry {
DdNode *f;
DdNode *g;
} HashEntry;
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddBddCorr.c,v 1.15 2012/02/05 01:07:18 fabio Exp $";
#endif
#ifdef CORREL_STATS
static int num_calls;
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static double bddCorrelationAux (DdManager *dd, DdNode *f, DdNode *g, st_table *table);
static double bddCorrelationWeightsAux (DdManager *dd, DdNode *f, DdNode *g, double *prob, st_table *table);
static int CorrelCompare (const char *key1, const char *key2);
static int CorrelHash (char *key, int modulus);
static enum st_retval CorrelCleanUp (char *key, char *value, char *arg);
/**AutomaticEnd***************************************************************/
#ifdef __cplusplus
}
#endif
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Computes the correlation of f and g.]
Description [Computes the correlation of f and g. If f == g, their
correlation is 1. If f == g', their correlation is 0. Returns the
fraction of minterms in the ON-set of the EXNOR of f and g. If it
runs out of memory, returns (double)CUDD_OUT_OF_MEM.]
SideEffects [None]
SeeAlso [Cudd_bddCorrelationWeights]
******************************************************************************/
double
Cudd_bddCorrelation(
DdManager * manager,
DdNode * f,
DdNode * g)
{
st_table *table;
double correlation;
#ifdef CORREL_STATS
num_calls = 0;
#endif
table = st_init_table(CorrelCompare,CorrelHash);
if (table == NULL) return((double)CUDD_OUT_OF_MEM);
correlation = bddCorrelationAux(manager,f,g,table);
st_foreach(table, CorrelCleanUp, NIL(char));
st_free_table(table);
return(correlation);
} /* end of Cudd_bddCorrelation */
/**Function********************************************************************
Synopsis [Computes the correlation of f and g for given input
probabilities.]
Description [Computes the correlation of f and g for given input
probabilities. On input, prob\[i\] is supposed to contain the
probability of the i-th input variable to be 1.
If f == g, their correlation is 1. If f == g', their
correlation is 0. Returns the probability that f and g have the same
value. If it runs out of memory, returns (double)CUDD_OUT_OF_MEM. The
correlation of f and the constant one gives the probability of f.]
SideEffects [None]
SeeAlso [Cudd_bddCorrelation]
******************************************************************************/
double
Cudd_bddCorrelationWeights(
DdManager * manager,
DdNode * f,
DdNode * g,
double * prob)
{
st_table *table;
double correlation;
#ifdef CORREL_STATS
num_calls = 0;
#endif
table = st_init_table(CorrelCompare,CorrelHash);
if (table == NULL) return((double)CUDD_OUT_OF_MEM);
correlation = bddCorrelationWeightsAux(manager,f,g,prob,table);
st_foreach(table, CorrelCleanUp, NIL(char));
st_free_table(table);
return(correlation);
} /* end of Cudd_bddCorrelationWeights */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_bddCorrelation.]
Description [Performs the recursive step of Cudd_bddCorrelation.
Returns the fraction of minterms in the ON-set of the EXNOR of f and
g.]
SideEffects [None]
SeeAlso [bddCorrelationWeightsAux]
******************************************************************************/
static double
bddCorrelationAux(
DdManager * dd,
DdNode * f,
DdNode * g,
st_table * table)
{
DdNode *Fv, *Fnv, *G, *Gv, *Gnv;
double min, *pmin, min1, min2, *dummy;
HashEntry *entry;
unsigned int topF, topG;
statLine(dd);
#ifdef CORREL_STATS
num_calls++;
#endif
/* Terminal cases: only work for BDDs. */
if (f == g) return(1.0);
if (f == Cudd_Not(g)) return(0.0);
/* Standardize call using the following properties:
** (f EXNOR g) = (g EXNOR f)
** (f' EXNOR g') = (f EXNOR g).
*/
if (f > g) {
DdNode *tmp = f;
f = g; g = tmp;
}
if (Cudd_IsComplement(f)) {
f = Cudd_Not(f);
g = Cudd_Not(g);
}
/* From now on, f is regular. */
entry = ALLOC(HashEntry,1);
if (entry == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(CUDD_OUT_OF_MEM);
}
entry->f = f; entry->g = g;
/* We do not use the fact that
** correlation(f,g') = 1 - correlation(f,g)
** to minimize the risk of cancellation.
*/
if (st_lookup(table, entry, &dummy)) {
min = *dummy;
FREE(entry);
return(min);
}
G = Cudd_Regular(g);
topF = cuddI(dd,f->index); topG = cuddI(dd,G->index);
if (topF <= topG) { Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; }
if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; }
if (g != G) {
Gv = Cudd_Not(Gv);
Gnv = Cudd_Not(Gnv);
}
min1 = bddCorrelationAux(dd, Fv, Gv, table) / 2.0;
if (min1 == (double)CUDD_OUT_OF_MEM) {
FREE(entry);
return(CUDD_OUT_OF_MEM);
}
min2 = bddCorrelationAux(dd, Fnv, Gnv, table) / 2.0;
if (min2 == (double)CUDD_OUT_OF_MEM) {
FREE(entry);
return(CUDD_OUT_OF_MEM);
}
min = (min1+min2);
pmin = ALLOC(double,1);
if (pmin == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return((double)CUDD_OUT_OF_MEM);
}
*pmin = min;
if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) {
FREE(entry);
FREE(pmin);
return((double)CUDD_OUT_OF_MEM);
}
return(min);
} /* end of bddCorrelationAux */
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_bddCorrelationWeigths.]
Description []
SideEffects [None]
SeeAlso [bddCorrelationAux]
******************************************************************************/
static double
bddCorrelationWeightsAux(
DdManager * dd,
DdNode * f,
DdNode * g,
double * prob,
st_table * table)
{
DdNode *Fv, *Fnv, *G, *Gv, *Gnv;
double min, *pmin, min1, min2, *dummy;
HashEntry *entry;
int topF, topG, index;
statLine(dd);
#ifdef CORREL_STATS
num_calls++;
#endif
/* Terminal cases: only work for BDDs. */
if (f == g) return(1.0);
if (f == Cudd_Not(g)) return(0.0);
/* Standardize call using the following properties:
** (f EXNOR g) = (g EXNOR f)
** (f' EXNOR g') = (f EXNOR g).
*/
if (f > g) {
DdNode *tmp = f;
f = g; g = tmp;
}
if (Cudd_IsComplement(f)) {
f = Cudd_Not(f);
g = Cudd_Not(g);
}
/* From now on, f is regular. */
entry = ALLOC(HashEntry,1);
if (entry == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return((double)CUDD_OUT_OF_MEM);
}
entry->f = f; entry->g = g;
/* We do not use the fact that
** correlation(f,g') = 1 - correlation(f,g)
** to minimize the risk of cancellation.
*/
if (st_lookup(table, entry, &dummy)) {
min = *dummy;
FREE(entry);
return(min);
}
G = Cudd_Regular(g);
topF = cuddI(dd,f->index); topG = cuddI(dd,G->index);
if (topF <= topG) {
Fv = cuddT(f); Fnv = cuddE(f);
index = f->index;
} else {
Fv = Fnv = f;
index = G->index;
}
if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; }
if (g != G) {
Gv = Cudd_Not(Gv);
Gnv = Cudd_Not(Gnv);
}
min1 = bddCorrelationWeightsAux(dd, Fv, Gv, prob, table) * prob[index];
if (min1 == (double)CUDD_OUT_OF_MEM) {
FREE(entry);
return((double)CUDD_OUT_OF_MEM);
}
min2 = bddCorrelationWeightsAux(dd, Fnv, Gnv, prob, table) * (1.0 - prob[index]);
if (min2 == (double)CUDD_OUT_OF_MEM) {
FREE(entry);
return((double)CUDD_OUT_OF_MEM);
}
min = (min1+min2);
pmin = ALLOC(double,1);
if (pmin == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return((double)CUDD_OUT_OF_MEM);
}
*pmin = min;
if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) {
FREE(entry);
FREE(pmin);
return((double)CUDD_OUT_OF_MEM);
}
return(min);
} /* end of bddCorrelationWeightsAux */
/**Function********************************************************************
Synopsis [Compares two hash table entries.]
Description [Compares two hash table entries. Returns 0 if they are
identical; 1 otherwise.]
SideEffects [None]
******************************************************************************/
static int
CorrelCompare(
const char * key1,
const char * key2)
{
HashEntry *entry1;
HashEntry *entry2;
entry1 = (HashEntry *) key1;
entry2 = (HashEntry *) key2;
if (entry1->f != entry2->f || entry1->g != entry2->g) return(1);
return(0);
} /* end of CorrelCompare */
/**Function********************************************************************
Synopsis [Hashes a hash table entry.]
Description [Hashes a hash table entry. It is patterned after
st_strhash. Returns a value between 0 and modulus.]
SideEffects [None]
******************************************************************************/
static int
CorrelHash(
char * key,
int modulus)
{
HashEntry *entry;
int val = 0;
entry = (HashEntry *) key;
#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
val = ((int) ((long)entry->f))*997 + ((int) ((long)entry->g));
#else
val = ((int) entry->f)*997 + ((int) entry->g);
#endif
return ((val < 0) ? -val : val) % modulus;
} /* end of CorrelHash */
/**Function********************************************************************
Synopsis [Frees memory associated with hash table.]
Description [Frees memory associated with hash table. Returns
ST_CONTINUE.]
SideEffects [None]
******************************************************************************/
static enum st_retval
CorrelCleanUp(
char * key,
char * value,
char * arg)
{
double *d;
HashEntry *entry;
entry = (HashEntry *) key;
FREE(entry);
d = (double *)value;
FREE(d);
return ST_CONTINUE;
} /* end of CorrelCleanUp */

1430
cudd_local/cudd/cuddBddIte.c Normal file

File diff suppressed because it is too large Load Diff

1016
cudd_local/cudd/cuddBridge.c Normal file

File diff suppressed because it is too large Load Diff

1053
cudd_local/cudd/cuddCache.c Normal file

File diff suppressed because it is too large Load Diff

885
cudd_local/cudd/cuddCheck.c Normal file
View File

@@ -0,0 +1,885 @@
/**CFile***********************************************************************
FileName [cuddCheck.c]
PackageName [cudd]
Synopsis [Functions to check consistency of data structures.]
Description [External procedures included in this module:
<ul>
<li> Cudd_DebugCheck()
<li> Cudd_CheckKeys()
</ul>
Internal procedures included in this module:
<ul>
<li> cuddHeapProfile()
<li> cuddPrintNode()
<li> cuddPrintVarGroups()
</ul>
Static procedures included in this module:
<ul>
<li> debugFindParent()
</ul>
]
SeeAlso []
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddCheck.c,v 1.37 2012/02/05 01:07:18 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static void debugFindParent (DdManager *table, DdNode *node);
#if 0
static void debugCheckParent (DdManager *table, DdNode *node);
#endif
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Checks for inconsistencies in the DD heap.]
Description [Checks for inconsistencies in the DD heap:
<ul>
<li> node has illegal index
<li> live node has dead children
<li> node has illegal Then or Else pointers
<li> BDD/ADD node has identical children
<li> ZDD node has zero then child
<li> wrong number of total nodes
<li> wrong number of dead nodes
<li> ref count error at node
</ul>
Returns 0 if no inconsistencies are found; DD_OUT_OF_MEM if there is
not enough memory; 1 otherwise.]
SideEffects [None]
SeeAlso [Cudd_CheckKeys]
******************************************************************************/
int
Cudd_DebugCheck(
DdManager * table)
{
unsigned int i;
int j,count;
int slots;
DdNodePtr *nodelist;
DdNode *f;
DdNode *sentinel = &(table->sentinel);
st_table *edgeTable; /* stores internal ref count for each node */
st_generator *gen;
int flag = 0;
int totalNode;
int deadNode;
int index;
int shift;
edgeTable = st_init_table(st_ptrcmp,st_ptrhash);
if (edgeTable == NULL) return(CUDD_OUT_OF_MEM);
/* Check the BDD/ADD subtables. */
for (i = 0; i < (unsigned) table->size; i++) {
index = table->invperm[i];
if (i != (unsigned) table->perm[index]) {
(void) fprintf(table->err,
"Permutation corrupted: invperm[%u] = %d\t perm[%d] = %d\n",
i, index, index, table->perm[index]);
}
nodelist = table->subtables[i].nodelist;
slots = table->subtables[i].slots;
shift = table->subtables[i].shift;
totalNode = 0;
deadNode = 0;
for (j = 0; j < slots; j++) { /* for each subtable slot */
f = nodelist[j];
while (f != sentinel) {
totalNode++;
if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) {
if ((int) f->index != index) {
(void) fprintf(table->err,
"Error: node has illegal index\n");
cuddPrintNode(f,table->err);
flag = 1;
}
if ((unsigned) cuddI(table,cuddT(f)->index) <= i ||
(unsigned) cuddI(table,Cudd_Regular(cuddE(f))->index)
<= i) {
(void) fprintf(table->err,
"Error: node has illegal children\n");
cuddPrintNode(f,table->err);
flag = 1;
}
if (Cudd_Regular(cuddT(f)) != cuddT(f)) {
(void) fprintf(table->err,
"Error: node has illegal form\n");
cuddPrintNode(f,table->err);
flag = 1;
}
if (cuddT(f) == cuddE(f)) {
(void) fprintf(table->err,
"Error: node has identical children\n");
cuddPrintNode(f,table->err);
flag = 1;
}
if (cuddT(f)->ref == 0 || Cudd_Regular(cuddE(f))->ref == 0) {
(void) fprintf(table->err,
"Error: live node has dead children\n");
cuddPrintNode(f,table->err);
flag =1;
}
if (ddHash(cuddT(f),cuddE(f),shift) != j) {
(void) fprintf(table->err, "Error: misplaced node\n");
cuddPrintNode(f,table->err);
flag =1;
}
/* Increment the internal reference count for the
** then child of the current node.
*/
if (st_lookup_int(edgeTable,(char *)cuddT(f),&count)) {
count++;
} else {
count = 1;
}
if (st_insert(edgeTable,(char *)cuddT(f),
(char *)(long)count) == ST_OUT_OF_MEM) {
st_free_table(edgeTable);
return(CUDD_OUT_OF_MEM);
}
/* Increment the internal reference count for the
** else child of the current node.
*/
if (st_lookup_int(edgeTable,(char *)Cudd_Regular(cuddE(f)),
&count)) {
count++;
} else {
count = 1;
}
if (st_insert(edgeTable,(char *)Cudd_Regular(cuddE(f)),
(char *)(long)count) == ST_OUT_OF_MEM) {
st_free_table(edgeTable);
return(CUDD_OUT_OF_MEM);
}
} else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) {
deadNode++;
#if 0
debugCheckParent(table,f);
#endif
} else {
fprintf(table->err,
"Error: node has illegal Then or Else pointers\n");
cuddPrintNode(f,table->err);
flag = 1;
}
f = f->next;
} /* for each element of the collision list */
} /* for each subtable slot */
if ((unsigned) totalNode != table->subtables[i].keys) {
fprintf(table->err,"Error: wrong number of total nodes\n");
flag = 1;
}
if ((unsigned) deadNode != table->subtables[i].dead) {
fprintf(table->err,"Error: wrong number of dead nodes\n");
flag = 1;
}
} /* for each BDD/ADD subtable */
/* Check the ZDD subtables. */
for (i = 0; i < (unsigned) table->sizeZ; i++) {
index = table->invpermZ[i];
if (i != (unsigned) table->permZ[index]) {
(void) fprintf(table->err,
"Permutation corrupted: invpermZ[%u] = %d\t permZ[%d] = %d in ZDD\n",
i, index, index, table->permZ[index]);
}
nodelist = table->subtableZ[i].nodelist;
slots = table->subtableZ[i].slots;
totalNode = 0;
deadNode = 0;
for (j = 0; j < slots; j++) { /* for each subtable slot */
f = nodelist[j];
while (f != NULL) {
totalNode++;
if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) {
if ((int) f->index != index) {
(void) fprintf(table->err,
"Error: ZDD node has illegal index\n");
cuddPrintNode(f,table->err);
flag = 1;
}
if (Cudd_IsComplement(cuddT(f)) ||
Cudd_IsComplement(cuddE(f))) {
(void) fprintf(table->err,
"Error: ZDD node has complemented children\n");
cuddPrintNode(f,table->err);
flag = 1;
}
if ((unsigned) cuddIZ(table,cuddT(f)->index) <= i ||
(unsigned) cuddIZ(table,cuddE(f)->index) <= i) {
(void) fprintf(table->err,
"Error: ZDD node has illegal children\n");
cuddPrintNode(f,table->err);
cuddPrintNode(cuddT(f),table->err);
cuddPrintNode(cuddE(f),table->err);
flag = 1;
}
if (cuddT(f) == DD_ZERO(table)) {
(void) fprintf(table->err,
"Error: ZDD node has zero then child\n");
cuddPrintNode(f,table->err);
flag = 1;
}
if (cuddT(f)->ref == 0 || cuddE(f)->ref == 0) {
(void) fprintf(table->err,
"Error: ZDD live node has dead children\n");
cuddPrintNode(f,table->err);
flag =1;
}
/* Increment the internal reference count for the
** then child of the current node.
*/
if (st_lookup_int(edgeTable,(char *)cuddT(f),&count)) {
count++;
} else {
count = 1;
}
if (st_insert(edgeTable,(char *)cuddT(f),
(char *)(long)count) == ST_OUT_OF_MEM) {
st_free_table(edgeTable);
return(CUDD_OUT_OF_MEM);
}
/* Increment the internal reference count for the
** else child of the current node.
*/
if (st_lookup_int(edgeTable,(char *)cuddE(f),&count)) {
count++;
} else {
count = 1;
}
if (st_insert(edgeTable,(char *)cuddE(f),
(char *)(long)count) == ST_OUT_OF_MEM) {
st_free_table(edgeTable);
table->errorCode = CUDD_MEMORY_OUT;
return(CUDD_OUT_OF_MEM);
}
} else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) {
deadNode++;
#if 0
debugCheckParent(table,f);
#endif
} else {
fprintf(table->err,
"Error: ZDD node has illegal Then or Else pointers\n");
cuddPrintNode(f,table->err);
flag = 1;
}
f = f->next;
} /* for each element of the collision list */
} /* for each subtable slot */
if ((unsigned) totalNode != table->subtableZ[i].keys) {
fprintf(table->err,
"Error: wrong number of total nodes in ZDD\n");
flag = 1;
}
if ((unsigned) deadNode != table->subtableZ[i].dead) {
fprintf(table->err,
"Error: wrong number of dead nodes in ZDD\n");
flag = 1;
}
} /* for each ZDD subtable */
/* Check the constant table. */
nodelist = table->constants.nodelist;
slots = table->constants.slots;
totalNode = 0;
deadNode = 0;
for (j = 0; j < slots; j++) {
f = nodelist[j];
while (f != NULL) {
totalNode++;
if (f->ref != 0) {
if (f->index != CUDD_CONST_INDEX) {
fprintf(table->err,"Error: node has illegal index\n");
#if SIZEOF_VOID_P == 8
fprintf(table->err,
" node 0x%lx, id = %u, ref = %u, value = %g\n",
(ptruint)f,f->index,f->ref,cuddV(f));
#else
fprintf(table->err,
" node 0x%x, id = %hu, ref = %hu, value = %g\n",
(ptruint)f,f->index,f->ref,cuddV(f));
#endif
flag = 1;
}
} else {
deadNode++;
}
f = f->next;
}
}
if ((unsigned) totalNode != table->constants.keys) {
(void) fprintf(table->err,
"Error: wrong number of total nodes in constants\n");
flag = 1;
}
if ((unsigned) deadNode != table->constants.dead) {
(void) fprintf(table->err,
"Error: wrong number of dead nodes in constants\n");
flag = 1;
}
gen = st_init_gen(edgeTable);
while (st_gen(gen, &f, &count)) {
if (count > (int)(f->ref) && f->ref != DD_MAXREF) {
#if SIZEOF_VOID_P == 8
fprintf(table->err,"ref count error at node 0x%lx, count = %d, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",(ptruint)f,count,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
#else
fprintf(table->err,"ref count error at node 0x%x, count = %d, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",(ptruint)f,count,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
#endif
debugFindParent(table,f);
flag = 1;
}
}
st_free_gen(gen);
st_free_table(edgeTable);
return (flag);
} /* end of Cudd_DebugCheck */
/**Function********************************************************************
Synopsis [Checks for several conditions that should not occur.]
Description [Checks for the following conditions:
<ul>
<li>Wrong sizes of subtables.
<li>Wrong number of keys found in unique subtable.
<li>Wrong number of dead found in unique subtable.
<li>Wrong number of keys found in the constant table
<li>Wrong number of dead found in the constant table
<li>Wrong number of total slots found
<li>Wrong number of maximum keys found
<li>Wrong number of total dead found
</ul>
Reports the average length of non-empty lists. Returns the number of
subtables for which the number of keys is wrong.]
SideEffects [None]
SeeAlso [Cudd_DebugCheck]
******************************************************************************/
int
Cudd_CheckKeys(
DdManager * table)
{
int size;
int i,j;
DdNodePtr *nodelist;
DdNode *node;
DdNode *sentinel = &(table->sentinel);
DdSubtable *subtable;
int keys;
int dead;
int count = 0;
int totalKeys = 0;
int totalSlots = 0;
int totalDead = 0;
int nonEmpty = 0;
unsigned int slots;
int logSlots;
int shift;
size = table->size;
for (i = 0; i < size; i++) {
subtable = &(table->subtables[i]);
nodelist = subtable->nodelist;
keys = subtable->keys;
dead = subtable->dead;
totalKeys += keys;
slots = subtable->slots;
shift = subtable->shift;
logSlots = sizeof(int) * 8 - shift;
if (((slots >> logSlots) << logSlots) != slots) {
(void) fprintf(table->err,
"Unique table %d is not the right power of 2\n", i);
(void) fprintf(table->err,
" slots = %u shift = %d\n", slots, shift);
}
totalSlots += slots;
totalDead += dead;
for (j = 0; (unsigned) j < slots; j++) {
node = nodelist[j];
if (node != sentinel) {
nonEmpty++;
}
while (node != sentinel) {
keys--;
if (node->ref == 0) {
dead--;
}
node = node->next;
}
}
if (keys != 0) {
(void) fprintf(table->err, "Wrong number of keys found \
in unique table %d (difference=%d)\n", i, keys);
count++;
}
if (dead != 0) {
(void) fprintf(table->err, "Wrong number of dead found \
in unique table no. %d (difference=%d)\n", i, dead);
}
} /* for each BDD/ADD subtable */
/* Check the ZDD subtables. */
size = table->sizeZ;
for (i = 0; i < size; i++) {
subtable = &(table->subtableZ[i]);
nodelist = subtable->nodelist;
keys = subtable->keys;
dead = subtable->dead;
totalKeys += keys;
totalSlots += subtable->slots;
totalDead += dead;
for (j = 0; (unsigned) j < subtable->slots; j++) {
node = nodelist[j];
if (node != NULL) {
nonEmpty++;
}
while (node != NULL) {
keys--;
if (node->ref == 0) {
dead--;
}
node = node->next;
}
}
if (keys != 0) {
(void) fprintf(table->err, "Wrong number of keys found \
in ZDD unique table no. %d (difference=%d)\n", i, keys);
count++;
}
if (dead != 0) {
(void) fprintf(table->err, "Wrong number of dead found \
in ZDD unique table no. %d (difference=%d)\n", i, dead);
}
} /* for each ZDD subtable */
/* Check the constant table. */
subtable = &(table->constants);
nodelist = subtable->nodelist;
keys = subtable->keys;
dead = subtable->dead;
totalKeys += keys;
totalSlots += subtable->slots;
totalDead += dead;
for (j = 0; (unsigned) j < subtable->slots; j++) {
node = nodelist[j];
if (node != NULL) {
nonEmpty++;
}
while (node != NULL) {
keys--;
if (node->ref == 0) {
dead--;
}
node = node->next;
}
}
if (keys != 0) {
(void) fprintf(table->err, "Wrong number of keys found \
in the constant table (difference=%d)\n", keys);
count++;
}
if (dead != 0) {
(void) fprintf(table->err, "Wrong number of dead found \
in the constant table (difference=%d)\n", dead);
}
if ((unsigned) totalKeys != table->keys + table->keysZ) {
(void) fprintf(table->err, "Wrong number of total keys found \
(difference=%d)\n", (int) (totalKeys-table->keys));
}
if ((unsigned) totalSlots != table->slots) {
(void) fprintf(table->err, "Wrong number of total slots found \
(difference=%d)\n", (int) (totalSlots-table->slots));
}
if (table->minDead != (unsigned) (table->gcFrac * table->slots)) {
(void) fprintf(table->err, "Wrong number of minimum dead found \
(%u vs. %u)\n", table->minDead,
(unsigned) (table->gcFrac * (double) table->slots));
}
if ((unsigned) totalDead != table->dead + table->deadZ) {
(void) fprintf(table->err, "Wrong number of total dead found \
(difference=%d)\n", (int) (totalDead-table->dead));
}
(void) fprintf(table->out,"Average length of non-empty lists = %g\n",
(double) table->keys / (double) nonEmpty);
return(count);
} /* end of Cudd_CheckKeys */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Prints information about the heap.]
Description [Prints to the manager's stdout the number of live nodes for each
level of the DD heap that contains at least one live node. It also
prints a summary containing:
<ul>
<li> total number of tables;
<li> number of tables with live nodes;
<li> table with the largest number of live nodes;
<li> number of nodes in that table.
</ul>
If more than one table contains the maximum number of live nodes,
only the one of lowest index is reported. Returns 1 in case of success
and 0 otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
int
cuddHeapProfile(
DdManager * dd)
{
int ntables = dd->size;
DdSubtable *subtables = dd->subtables;
int i, /* loop index */
nodes, /* live nodes in i-th layer */
retval, /* return value of fprintf */
largest = -1, /* index of the table with most live nodes */
maxnodes = -1, /* maximum number of live nodes in a table */
nonempty = 0; /* number of tables with live nodes */
/* Print header. */
#if SIZEOF_VOID_P == 8
retval = fprintf(dd->out,"*** DD heap profile for 0x%lx ***\n",
(ptruint) dd);
#else
retval = fprintf(dd->out,"*** DD heap profile for 0x%x ***\n",
(ptruint) dd);
#endif
if (retval == EOF) return 0;
/* Print number of live nodes for each nonempty table. */
for (i=0; i<ntables; i++) {
nodes = subtables[i].keys - subtables[i].dead;
if (nodes) {
nonempty++;
retval = fprintf(dd->out,"%5d: %5d nodes\n", i, nodes);
if (retval == EOF) return 0;
if (nodes > maxnodes) {
maxnodes = nodes;
largest = i;
}
}
}
nodes = dd->constants.keys - dd->constants.dead;
if (nodes) {
nonempty++;
retval = fprintf(dd->out,"const: %5d nodes\n", nodes);
if (retval == EOF) return 0;
if (nodes > maxnodes) {
maxnodes = nodes;
largest = CUDD_CONST_INDEX;
}
}
/* Print summary. */
retval = fprintf(dd->out,"Summary: %d tables, %d non-empty, largest: %d ",
ntables+1, nonempty, largest);
if (retval == EOF) return 0;
retval = fprintf(dd->out,"(with %d nodes)\n", maxnodes);
if (retval == EOF) return 0;
return(1);
} /* end of cuddHeapProfile */
/**Function********************************************************************
Synopsis [Prints out information on a node.]
Description [Prints out information on a node.]
SideEffects [None]
SeeAlso []
******************************************************************************/
void
cuddPrintNode(
DdNode * f,
FILE *fp)
{
f = Cudd_Regular(f);
#if SIZEOF_VOID_P == 8
(void) fprintf(fp," node 0x%lx, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",(ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
#else
(void) fprintf(fp," node 0x%x, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",(ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
#endif
} /* end of cuddPrintNode */
/**Function********************************************************************
Synopsis [Prints the variable groups as a parenthesized list.]
Description [Prints the variable groups as a parenthesized list.
For each group the level range that it represents is printed. After
each group, the group's flags are printed, preceded by a `|'. For
each flag (except MTR_TERMINAL) a character is printed.
<ul>
<li>F: MTR_FIXED
<li>N: MTR_NEWNODE
<li>S: MTR_SOFT
</ul>
The second argument, silent, if different from 0, causes
Cudd_PrintVarGroups to only check the syntax of the group tree.]
SideEffects [None]
SeeAlso []
******************************************************************************/
void
cuddPrintVarGroups(
DdManager * dd /* manager */,
MtrNode * root /* root of the group tree */,
int zdd /* 0: BDD; 1: ZDD */,
int silent /* flag to check tree syntax only */)
{
MtrNode *node;
int level;
assert(root != NULL);
assert(root->younger == NULL || root->younger->elder == root);
assert(root->elder == NULL || root->elder->younger == root);
if (zdd) {
level = dd->permZ[root->index];
} else {
level = dd->perm[root->index];
}
if (!silent) (void) printf("(%d",level);
if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) {
if (!silent) (void) printf(",");
} else {
node = root->child;
while (node != NULL) {
assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size));
assert(node->parent == root);
cuddPrintVarGroups(dd,node,zdd,silent);
node = node->younger;
}
}
if (!silent) {
(void) printf("%d", (int) (level + root->size - 1));
if (root->flags != MTR_DEFAULT) {
(void) printf("|");
if (MTR_TEST(root,MTR_FIXED)) (void) printf("F");
if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N");
if (MTR_TEST(root,MTR_SOFT)) (void) printf("S");
}
(void) printf(")");
if (root->parent == NULL) (void) printf("\n");
}
assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0);
return;
} /* end of cuddPrintVarGroups */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Searches the subtables above node for its parents.]
Description []
SideEffects [None]
SeeAlso []
******************************************************************************/
static void
debugFindParent(
DdManager * table,
DdNode * node)
{
int i,j;
int slots;
DdNodePtr *nodelist;
DdNode *f;
for (i = 0; i < cuddI(table,node->index); i++) {
nodelist = table->subtables[i].nodelist;
slots = table->subtables[i].slots;
for (j=0;j<slots;j++) {
f = nodelist[j];
while (f != NULL) {
if (cuddT(f) == node || Cudd_Regular(cuddE(f)) == node) {
#if SIZEOF_VOID_P == 8
(void) fprintf(table->out,"parent is at 0x%lx, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",
(ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
#else
(void) fprintf(table->out,"parent is at 0x%x, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",
(ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f));
#endif
}
f = f->next;
}
}
}
} /* end of debugFindParent */
#if 0
/**Function********************************************************************
Synopsis [Reports an error if a (dead) node has a non-dead parent.]
Description [Searches all the subtables above node. Very expensive.
The same check is now implemented more efficiently in ddDebugCheck.]
SideEffects [None]
SeeAlso [debugFindParent]
******************************************************************************/
static void
debugCheckParent(
DdManager * table,
DdNode * node)
{
int i,j;
int slots;
DdNode **nodelist,*f;
for (i = 0; i < cuddI(table,node->index); i++) {
nodelist = table->subtables[i].nodelist;
slots = table->subtables[i].slots;
for (j=0;j<slots;j++) {
f = nodelist[j];
while (f != NULL) {
if ((Cudd_Regular(cuddE(f)) == node || cuddT(f) == node) && f->ref != 0) {
(void) fprintf(table->err,
"error with zero ref count\n");
(void) fprintf(table->err,"parent is 0x%x, id = %u, ref = %u, then = 0x%x, else = 0x%x\n",f,f->index,f->ref,cuddT(f),cuddE(f));
(void) fprintf(table->err,"child is 0x%x, id = %u, ref = %u, then = 0x%x, else = 0x%x\n",node,node->index,node->ref,cuddT(node),cuddE(node));
}
f = f->next;
}
}
}
}
#endif

558
cudd_local/cudd/cuddClip.c Normal file
View File

@@ -0,0 +1,558 @@
/**CFile***********************************************************************
FileName [cuddClip.c]
PackageName [cudd]
Synopsis [Clipping functions.]
Description [External procedures included in this module:
<ul>
<li> Cudd_bddClippingAnd()
<li> Cudd_bddClippingAndAbstract()
</ul>
Internal procedures included in this module:
<ul>
<li> cuddBddClippingAnd()
<li> cuddBddClippingAndAbstract()
</ul>
Static procedures included in this module:
<ul>
<li> cuddBddClippingAndRecur()
<li> cuddBddClipAndAbsRecur()
</ul>
SeeAlso []
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddClip.c,v 1.9 2012/02/05 01:07:18 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static DdNode * cuddBddClippingAndRecur (DdManager *manager, DdNode *f, DdNode *g, int distance, int direction);
static DdNode * cuddBddClipAndAbsRecur (DdManager *manager, DdNode *f, DdNode *g, DdNode *cube, int distance, int direction);
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Approximates the conjunction of two BDDs f and g.]
Description [Approximates the conjunction of two BDDs f and g. Returns a
pointer to the resulting BDD if successful; NULL if the intermediate
result blows up.]
SideEffects [None]
SeeAlso [Cudd_bddAnd]
******************************************************************************/
DdNode *
Cudd_bddClippingAnd(
DdManager * dd /* manager */,
DdNode * f /* first conjunct */,
DdNode * g /* second conjunct */,
int maxDepth /* maximum recursion depth */,
int direction /* under (0) or over (1) approximation */)
{
DdNode *res;
do {
dd->reordered = 0;
res = cuddBddClippingAnd(dd,f,g,maxDepth,direction);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_bddClippingAnd */
/**Function********************************************************************
Synopsis [Approximates the conjunction of two BDDs f and g and
simultaneously abstracts the variables in cube.]
Description [Approximates the conjunction of two BDDs f and g and
simultaneously abstracts the variables in cube. The variables are
existentially abstracted. Returns a pointer to the resulting BDD if
successful; NULL if the intermediate result blows up.]
SideEffects [None]
SeeAlso [Cudd_bddAndAbstract Cudd_bddClippingAnd]
******************************************************************************/
DdNode *
Cudd_bddClippingAndAbstract(
DdManager * dd /* manager */,
DdNode * f /* first conjunct */,
DdNode * g /* second conjunct */,
DdNode * cube /* cube of variables to be abstracted */,
int maxDepth /* maximum recursion depth */,
int direction /* under (0) or over (1) approximation */)
{
DdNode *res;
do {
dd->reordered = 0;
res = cuddBddClippingAndAbstract(dd,f,g,cube,maxDepth,direction);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_bddClippingAndAbstract */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Approximates the conjunction of two BDDs f and g.]
Description [Approximates the conjunction of two BDDs f and g. Returns a
pointer to the resulting BDD if successful; NULL if the intermediate
result blows up.]
SideEffects [None]
SeeAlso [Cudd_bddClippingAnd]
******************************************************************************/
DdNode *
cuddBddClippingAnd(
DdManager * dd /* manager */,
DdNode * f /* first conjunct */,
DdNode * g /* second conjunct */,
int maxDepth /* maximum recursion depth */,
int direction /* under (0) or over (1) approximation */)
{
DdNode *res;
res = cuddBddClippingAndRecur(dd,f,g,maxDepth,direction);
return(res);
} /* end of cuddBddClippingAnd */
/**Function********************************************************************
Synopsis [Approximates the conjunction of two BDDs f and g and
simultaneously abstracts the variables in cube.]
Description [Approximates the conjunction of two BDDs f and g and
simultaneously abstracts the variables in cube. Returns a
pointer to the resulting BDD if successful; NULL if the intermediate
result blows up.]
SideEffects [None]
SeeAlso [Cudd_bddClippingAndAbstract]
******************************************************************************/
DdNode *
cuddBddClippingAndAbstract(
DdManager * dd /* manager */,
DdNode * f /* first conjunct */,
DdNode * g /* second conjunct */,
DdNode * cube /* cube of variables to be abstracted */,
int maxDepth /* maximum recursion depth */,
int direction /* under (0) or over (1) approximation */)
{
DdNode *res;
res = cuddBddClipAndAbsRecur(dd,f,g,cube,maxDepth,direction);
return(res);
} /* end of cuddBddClippingAndAbstract */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Implements the recursive step of Cudd_bddClippingAnd.]
Description [Implements the recursive step of Cudd_bddClippingAnd by taking
the conjunction of two BDDs. Returns a pointer to the result is
successful; NULL otherwise.]
SideEffects [None]
SeeAlso [cuddBddClippingAnd]
******************************************************************************/
static DdNode *
cuddBddClippingAndRecur(
DdManager * manager,
DdNode * f,
DdNode * g,
int distance,
int direction)
{
DdNode *F, *ft, *fe, *G, *gt, *ge;
DdNode *one, *zero, *r, *t, *e;
unsigned int topf, topg, index;
DD_CTFP cacheOp;
statLine(manager);
one = DD_ONE(manager);
zero = Cudd_Not(one);
/* Terminal cases. */
if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
if (f == g || g == one) return(f);
if (f == one) return(g);
if (distance == 0) {
/* One last attempt at returning the right result. We sort of
** cheat by calling Cudd_bddLeq. */
if (Cudd_bddLeq(manager,f,g)) return(f);
if (Cudd_bddLeq(manager,g,f)) return(g);
if (direction == 1) {
if (Cudd_bddLeq(manager,f,Cudd_Not(g)) ||
Cudd_bddLeq(manager,g,Cudd_Not(f))) return(zero);
}
return(Cudd_NotCond(one,(direction == 0)));
}
/* At this point f and g are not constant. */
distance--;
/* Check cache. Try to increase cache efficiency by sorting the
** pointers. */
if (f > g) {
DdNode *tmp = f;
f = g; g = tmp;
}
F = Cudd_Regular(f);
G = Cudd_Regular(g);
cacheOp = (DD_CTFP)
(direction ? Cudd_bddClippingAnd : cuddBddClippingAnd);
if (F->ref != 1 || G->ref != 1) {
r = cuddCacheLookup2(manager, cacheOp, f, g);
if (r != NULL) return(r);
}
/* Here we can skip the use of cuddI, because the operands are known
** to be non-constant.
*/
topf = manager->perm[F->index];
topg = manager->perm[G->index];
/* Compute cofactors. */
if (topf <= topg) {
index = F->index;
ft = cuddT(F);
fe = cuddE(F);
if (Cudd_IsComplement(f)) {
ft = Cudd_Not(ft);
fe = Cudd_Not(fe);
}
} else {
index = G->index;
ft = fe = f;
}
if (topg <= topf) {
gt = cuddT(G);
ge = cuddE(G);
if (Cudd_IsComplement(g)) {
gt = Cudd_Not(gt);
ge = Cudd_Not(ge);
}
} else {
gt = ge = g;
}
t = cuddBddClippingAndRecur(manager, ft, gt, distance, direction);
if (t == NULL) return(NULL);
cuddRef(t);
e = cuddBddClippingAndRecur(manager, fe, ge, distance, direction);
if (e == NULL) {
Cudd_RecursiveDeref(manager, t);
return(NULL);
}
cuddRef(e);
if (t == e) {
r = t;
} else {
if (Cudd_IsComplement(t)) {
r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
if (r == NULL) {
Cudd_RecursiveDeref(manager, t);
Cudd_RecursiveDeref(manager, e);
return(NULL);
}
r = Cudd_Not(r);
} else {
r = cuddUniqueInter(manager,(int)index,t,e);
if (r == NULL) {
Cudd_RecursiveDeref(manager, t);
Cudd_RecursiveDeref(manager, e);
return(NULL);
}
}
}
cuddDeref(e);
cuddDeref(t);
if (F->ref != 1 || G->ref != 1)
cuddCacheInsert2(manager, cacheOp, f, g, r);
return(r);
} /* end of cuddBddClippingAndRecur */
/**Function********************************************************************
Synopsis [Approximates the AND of two BDDs and simultaneously abstracts the
variables in cube.]
Description [Approximates the AND of two BDDs and simultaneously
abstracts the variables in cube. The variables are existentially
abstracted. Returns a pointer to the result is successful; NULL
otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddClippingAndAbstract]
******************************************************************************/
static DdNode *
cuddBddClipAndAbsRecur(
DdManager * manager,
DdNode * f,
DdNode * g,
DdNode * cube,
int distance,
int direction)
{
DdNode *F, *ft, *fe, *G, *gt, *ge;
DdNode *one, *zero, *r, *t, *e, *Cube;
unsigned int topf, topg, topcube, top, index;
ptruint cacheTag;
statLine(manager);
one = DD_ONE(manager);
zero = Cudd_Not(one);
/* Terminal cases. */
if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
if (f == one && g == one) return(one);
if (cube == one) {
return(cuddBddClippingAndRecur(manager, f, g, distance, direction));
}
if (f == one || f == g) {
return (cuddBddExistAbstractRecur(manager, g, cube));
}
if (g == one) {
return (cuddBddExistAbstractRecur(manager, f, cube));
}
if (distance == 0) return(Cudd_NotCond(one,(direction == 0)));
/* At this point f, g, and cube are not constant. */
distance--;
/* Check cache. */
if (f > g) { /* Try to increase cache efficiency. */
DdNode *tmp = f;
f = g; g = tmp;
}
F = Cudd_Regular(f);
G = Cudd_Regular(g);
cacheTag = direction ? DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG :
DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG;
if (F->ref != 1 || G->ref != 1) {
r = cuddCacheLookup(manager, cacheTag,
f, g, cube);
if (r != NULL) {
return(r);
}
}
/* Here we can skip the use of cuddI, because the operands are known
** to be non-constant.
*/
topf = manager->perm[F->index];
topg = manager->perm[G->index];
top = ddMin(topf, topg);
topcube = manager->perm[cube->index];
if (topcube < top) {
return(cuddBddClipAndAbsRecur(manager, f, g, cuddT(cube),
distance, direction));
}
/* Now, topcube >= top. */
if (topf == top) {
index = F->index;
ft = cuddT(F);
fe = cuddE(F);
if (Cudd_IsComplement(f)) {
ft = Cudd_Not(ft);
fe = Cudd_Not(fe);
}
} else {
index = G->index;
ft = fe = f;
}
if (topg == top) {
gt = cuddT(G);
ge = cuddE(G);
if (Cudd_IsComplement(g)) {
gt = Cudd_Not(gt);
ge = Cudd_Not(ge);
}
} else {
gt = ge = g;
}
if (topcube == top) {
Cube = cuddT(cube);
} else {
Cube = cube;
}
t = cuddBddClipAndAbsRecur(manager, ft, gt, Cube, distance, direction);
if (t == NULL) return(NULL);
/* Special case: 1 OR anything = 1. Hence, no need to compute
** the else branch if t is 1.
*/
if (t == one && topcube == top) {
if (F->ref != 1 || G->ref != 1)
cuddCacheInsert(manager, cacheTag, f, g, cube, one);
return(one);
}
cuddRef(t);
e = cuddBddClipAndAbsRecur(manager, fe, ge, Cube, distance, direction);
if (e == NULL) {
Cudd_RecursiveDeref(manager, t);
return(NULL);
}
cuddRef(e);
if (topcube == top) { /* abstract */
r = cuddBddClippingAndRecur(manager, Cudd_Not(t), Cudd_Not(e),
distance, (direction == 0));
if (r == NULL) {
Cudd_RecursiveDeref(manager, t);
Cudd_RecursiveDeref(manager, e);
return(NULL);
}
r = Cudd_Not(r);
cuddRef(r);
Cudd_RecursiveDeref(manager, t);
Cudd_RecursiveDeref(manager, e);
cuddDeref(r);
} else if (t == e) {
r = t;
cuddDeref(t);
cuddDeref(e);
} else {
if (Cudd_IsComplement(t)) {
r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
if (r == NULL) {
Cudd_RecursiveDeref(manager, t);
Cudd_RecursiveDeref(manager, e);
return(NULL);
}
r = Cudd_Not(r);
} else {
r = cuddUniqueInter(manager,(int)index,t,e);
if (r == NULL) {
Cudd_RecursiveDeref(manager, t);
Cudd_RecursiveDeref(manager, e);
return(NULL);
}
}
cuddDeref(e);
cuddDeref(t);
}
if (F->ref != 1 || G->ref != 1)
cuddCacheInsert(manager, cacheTag, f, g, cube, r);
return (r);
} /* end of cuddBddClipAndAbsRecur */

327
cudd_local/cudd/cuddCof.c Normal file
View File

@@ -0,0 +1,327 @@
/**CFile***********************************************************************
FileName [cuddCof.c]
PackageName [cudd]
Synopsis [Cofactoring functions.]
Description [External procedures included in this module:
<ul>
<li> Cudd_Cofactor()
<li> Cudd_CheckCube()
</ul>
Internal procedures included in this module:
<ul>
<li> cuddGetBranches()
<li> cuddCofactorRecur()
</ul>
]
SeeAlso []
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddCof.c,v 1.11 2012/02/05 01:07:18 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Computes the cofactor of f with respect to g.]
Description [Computes the cofactor of f with respect to g; g must be
the BDD or the ADD of a cube. Returns a pointer to the cofactor if
successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddConstrain Cudd_bddRestrict]
******************************************************************************/
DdNode *
Cudd_Cofactor(
DdManager * dd,
DdNode * f,
DdNode * g)
{
DdNode *res,*zero;
zero = Cudd_Not(DD_ONE(dd));
if (g == zero || g == DD_ZERO(dd)) {
(void) fprintf(dd->err,"Cudd_Cofactor: Invalid restriction 1\n");
dd->errorCode = CUDD_INVALID_ARG;
return(NULL);
}
do {
dd->reordered = 0;
res = cuddCofactorRecur(dd,f,g);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_Cofactor */
/**Function********************************************************************
Synopsis [Checks whether g is the BDD of a cube.]
Description [Checks whether g is the BDD of a cube. Returns 1 in case
of success; 0 otherwise. The constant 1 is a valid cube, but all other
constant functions cause cuddCheckCube to return 0.]
SideEffects [None]
SeeAlso []
******************************************************************************/
int
Cudd_CheckCube(
DdManager * dd,
DdNode * g)
{
DdNode *g1,*g0,*one,*zero;
one = DD_ONE(dd);
if (g == one) return(1);
if (Cudd_IsConstant(g)) return(0);
zero = Cudd_Not(one);
cuddGetBranches(g,&g1,&g0);
if (g0 == zero) {
return(Cudd_CheckCube(dd, g1));
}
if (g1 == zero) {
return(Cudd_CheckCube(dd, g0));
}
return(0);
} /* end of Cudd_CheckCube */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Computes the children of g.]
Description []
SideEffects [None]
SeeAlso []
******************************************************************************/
void
cuddGetBranches(
DdNode * g,
DdNode ** g1,
DdNode ** g0)
{
DdNode *G = Cudd_Regular(g);
*g1 = cuddT(G);
*g0 = cuddE(G);
if (Cudd_IsComplement(g)) {
*g1 = Cudd_Not(*g1);
*g0 = Cudd_Not(*g0);
}
} /* end of cuddGetBranches */
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_Cofactor.]
Description [Performs the recursive step of Cudd_Cofactor. Returns a
pointer to the cofactor if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_Cofactor]
******************************************************************************/
DdNode *
cuddCofactorRecur(
DdManager * dd,
DdNode * f,
DdNode * g)
{
DdNode *one,*zero,*F,*G,*g1,*g0,*f1,*f0,*t,*e,*r;
unsigned int topf,topg;
int comple;
statLine(dd);
F = Cudd_Regular(f);
if (cuddIsConstant(F)) return(f);
one = DD_ONE(dd);
/* The invariant g != 0 is true on entry to this procedure and is
** recursively maintained by it. Therefore it suffices to test g
** against one to make sure it is not constant.
*/
if (g == one) return(f);
/* From now on, f and g are known not to be constants. */
comple = f != F;
r = cuddCacheLookup2(dd,Cudd_Cofactor,F,g);
if (r != NULL) {
return(Cudd_NotCond(r,comple));
}
topf = dd->perm[F->index];
G = Cudd_Regular(g);
topg = dd->perm[G->index];
/* We take the cofactors of F because we are going to rely on
** the fact that the cofactors of the complement are the complements
** of the cofactors to better utilize the cache. Variable comple
** remembers whether we have to complement the result or not.
*/
if (topf <= topg) {
f1 = cuddT(F); f0 = cuddE(F);
} else {
f1 = f0 = F;
}
if (topg <= topf) {
g1 = cuddT(G); g0 = cuddE(G);
if (g != G) { g1 = Cudd_Not(g1); g0 = Cudd_Not(g0); }
} else {
g1 = g0 = g;
}
zero = Cudd_Not(one);
if (topf >= topg) {
if (g0 == zero || g0 == DD_ZERO(dd)) {
r = cuddCofactorRecur(dd, f1, g1);
} else if (g1 == zero || g1 == DD_ZERO(dd)) {
r = cuddCofactorRecur(dd, f0, g0);
} else {
(void) fprintf(dd->out,
"Cudd_Cofactor: Invalid restriction 2\n");
dd->errorCode = CUDD_INVALID_ARG;
return(NULL);
}
if (r == NULL) return(NULL);
} else /* if (topf < topg) */ {
t = cuddCofactorRecur(dd, f1, g);
if (t == NULL) return(NULL);
cuddRef(t);
e = cuddCofactorRecur(dd, f0, g);
if (e == NULL) {
Cudd_RecursiveDeref(dd, t);
return(NULL);
}
cuddRef(e);
if (t == e) {
r = t;
} else if (Cudd_IsComplement(t)) {
r = cuddUniqueInter(dd,(int)F->index,Cudd_Not(t),Cudd_Not(e));
if (r != NULL)
r = Cudd_Not(r);
} else {
r = cuddUniqueInter(dd,(int)F->index,t,e);
}
if (r == NULL) {
Cudd_RecursiveDeref(dd ,e);
Cudd_RecursiveDeref(dd ,t);
return(NULL);
}
cuddDeref(t);
cuddDeref(e);
}
cuddCacheInsert2(dd,Cudd_Cofactor,F,g,r);
return(Cudd_NotCond(r,comple));
} /* end of cuddCofactorRecur */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

2177
cudd_local/cudd/cuddDecomp.c Normal file

File diff suppressed because it is too large Load Diff

1467
cudd_local/cudd/cuddEssent.c Normal file

File diff suppressed because it is too large Load Diff

1020
cudd_local/cudd/cuddExact.c Normal file

File diff suppressed because it is too large Load Diff

1389
cudd_local/cudd/cuddExport.c Normal file

File diff suppressed because it is too large Load Diff

2178
cudd_local/cudd/cuddGenCof.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,960 @@
/**CFile***********************************************************************
FileName [cuddGenetic.c]
PackageName [cudd]
Synopsis [Genetic algorithm for variable reordering.]
Description [Internal procedures included in this file:
<ul>
<li> cuddGa()
</ul>
Static procedures included in this module:
<ul>
<li> make_random()
<li> sift_up()
<li> build_dd()
<li> largest()
<li> rand_int()
<li> array_hash()
<li> array_compare()
<li> find_best()
<li> find_average_fitness()
<li> PMX()
<li> roulette()
</ul>
The genetic algorithm implemented here is as follows. We start with
the current DD order. We sift this order and use this as the
reference DD. We only keep 1 DD around for the entire process and
simply rearrange the order of this DD, storing the various orders
and their corresponding DD sizes. We generate more random orders to
build an initial population. This initial population is 3 times the
number of variables, with a maximum of 120. Each random order is
built (from the reference DD) and its size stored. Each random
order is also sifted to keep the DD sizes fairly small. Then a
crossover is performed between two orders (picked randomly) and the
two resulting DDs are built and sifted. For each new order, if its
size is smaller than any DD in the population, it is inserted into
the population and the DD with the largest number of nodes is thrown
out. The crossover process happens up to 50 times, and at this point
the DD in the population with the smallest size is chosen as the
result. This DD must then be built from the reference DD.]
SeeAlso []
Author [Curt Musfeldt, Alan Shuler, Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddGenetic.c,v 1.30 2012/02/05 01:07:18 fabio Exp $";
#endif
static int popsize; /* the size of the population */
static int numvars; /* the number of input variables in the ckt. */
/* storedd stores the population orders and sizes. This table has two
** extra rows and one extras column. The two extra rows are used for the
** offspring produced by a crossover. Each row stores one order and its
** size. The order is stored by storing the indices of variables in the
** order in which they appear in the order. The table is in reality a
** one-dimensional array which is accessed via a macro to give the illusion
** it is a two-dimensional structure.
*/
static int *storedd;
static st_table *computed; /* hash table to identify existing orders */
static int *repeat; /* how many times an order is present */
static int large; /* stores the index of the population with
** the largest number of nodes in the DD */
static int result;
static int cross; /* the number of crossovers to perform */
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/* macro used to access the population table as if it were a
** two-dimensional structure.
*/
#define STOREDD(i,j) storedd[(i)*(numvars+1)+(j)]
#ifdef __cplusplus
extern "C" {
#endif
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static int make_random (DdManager *table, int lower);
static int sift_up (DdManager *table, int x, int x_low);
static int build_dd (DdManager *table, int num, int lower, int upper);
static int largest (void);
static int rand_int (int a);
static int array_hash (char *array, int modulus);
static int array_compare (const char *array1, const char *array2);
static int find_best (void);
#ifdef DD_STATS
static double find_average_fitness (void);
#endif
static int PMX (int maxvar);
static int roulette (int *p1, int *p2);
/**AutomaticEnd***************************************************************/
#ifdef __cplusplus
}
#endif
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Genetic algorithm for DD reordering.]
Description [Genetic algorithm for DD reordering.
The two children of a crossover will be stored in
storedd[popsize] and storedd[popsize+1] --- the last two slots in the
storedd array. (This will make comparisons and replacement easy.)
Returns 1 in case of success; 0 otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
int
cuddGa(
DdManager * table /* manager */,
int lower /* lowest level to be reordered */,
int upper /* highest level to be reorderded */)
{
int i,n,m; /* dummy/loop vars */
int index;
#ifdef DD_STATS
double average_fitness;
#endif
int small; /* index of smallest DD in population */
/* Do an initial sifting to produce at least one reasonable individual. */
if (!cuddSifting(table,lower,upper)) return(0);
/* Get the initial values. */
numvars = upper - lower + 1; /* number of variables to be reordered */
if (table->populationSize == 0) {
popsize = 3 * numvars; /* population size is 3 times # of vars */
if (popsize > 120) {
popsize = 120; /* Maximum population size is 120 */
}
} else {
popsize = table->populationSize; /* user specified value */
}
if (popsize < 4) popsize = 4; /* enforce minimum population size */
/* Allocate population table. */
storedd = ALLOC(int,(popsize+2)*(numvars+1));
if (storedd == NULL) {
table->errorCode = CUDD_MEMORY_OUT;
return(0);
}
/* Initialize the computed table. This table is made up of two data
** structures: A hash table with the key given by the order, which says
** if a given order is present in the population; and the repeat
** vector, which says how many copies of a given order are stored in
** the population table. If there are multiple copies of an order, only
** one has a repeat count greater than 1. This copy is the one pointed
** by the computed table.
*/
repeat = ALLOC(int,popsize);
if (repeat == NULL) {
table->errorCode = CUDD_MEMORY_OUT;
FREE(storedd);
return(0);
}
for (i = 0; i < popsize; i++) {
repeat[i] = 0;
}
computed = st_init_table(array_compare,array_hash);
if (computed == NULL) {
table->errorCode = CUDD_MEMORY_OUT;
FREE(storedd);
FREE(repeat);
return(0);
}
/* Copy the current DD and its size to the population table. */
for (i = 0; i < numvars; i++) {
STOREDD(0,i) = table->invperm[i+lower]; /* order of initial DD */
}
STOREDD(0,numvars) = table->keys - table->isolated; /* size of initial DD */
/* Store the initial order in the computed table. */
if (st_insert(computed,(char *)storedd,(char *) 0) == ST_OUT_OF_MEM) {
FREE(storedd);
FREE(repeat);
st_free_table(computed);
return(0);
}
repeat[0]++;
/* Insert the reverse order as second element of the population. */
for (i = 0; i < numvars; i++) {
STOREDD(1,numvars-1-i) = table->invperm[i+lower]; /* reverse order */
}
/* Now create the random orders. make_random fills the population
** table with random permutations. The successive loop builds and sifts
** the DDs for the reverse order and each random permutation, and stores
** the results in the computed table.
*/
if (!make_random(table,lower)) {
table->errorCode = CUDD_MEMORY_OUT;
FREE(storedd);
FREE(repeat);
st_free_table(computed);
return(0);
}
for (i = 1; i < popsize; i++) {
result = build_dd(table,i,lower,upper); /* build and sift order */
if (!result) {
FREE(storedd);
FREE(repeat);
st_free_table(computed);
return(0);
}
if (st_lookup_int(computed,(char *)&STOREDD(i,0),&index)) {
repeat[index]++;
} else {
if (st_insert(computed,(char *)&STOREDD(i,0),(char *)(long)i) ==
ST_OUT_OF_MEM) {
FREE(storedd);
FREE(repeat);
st_free_table(computed);
return(0);
}
repeat[i]++;
}
}
#if 0
#ifdef DD_STATS
/* Print the initial population. */
(void) fprintf(table->out,"Initial population after sifting\n");
for (m = 0; m < popsize; m++) {
for (i = 0; i < numvars; i++) {
(void) fprintf(table->out," %2d",STOREDD(m,i));
}
(void) fprintf(table->out," : %3d (%d)\n",
STOREDD(m,numvars),repeat[m]);
}
#endif
#endif
small = find_best();
#ifdef DD_STATS
average_fitness = find_average_fitness();
(void) fprintf(table->out,"\nInitial population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness);
#endif
/* Decide how many crossovers should be tried. */
if (table->numberXovers == 0) {
cross = 3*numvars;
if (cross > 60) { /* do a maximum of 50 crossovers */
cross = 60;
}
} else {
cross = table->numberXovers; /* use user specified value */
}
if (cross >= popsize) {
cross = popsize;
}
/* Perform the crossovers to get the best order. */
for (m = 0; m < cross; m++) {
if (!PMX(table->size)) { /* perform one crossover */
table->errorCode = CUDD_MEMORY_OUT;
FREE(storedd);
FREE(repeat);
st_free_table(computed);
return(0);
}
/* The offsprings are left in the last two entries of the
** population table. These are now considered in turn.
*/
for (i = popsize; i <= popsize+1; i++) {
result = build_dd(table,i,lower,upper); /* build and sift child */
if (!result) {
FREE(storedd);
FREE(repeat);
st_free_table(computed);
return(0);
}
large = largest(); /* find the largest DD in population */
/* If the new child is smaller than the largest DD in the current
** population, enter it into the population in place of the
** largest DD.
*/
if (STOREDD(i,numvars) < STOREDD(large,numvars)) {
/* Look up the largest DD in the computed table.
** Decrease its repetition count. If the repetition count
** goes to 0, remove the largest DD from the computed table.
*/
result = st_lookup_int(computed,(char *)&STOREDD(large,0),
&index);
if (!result) {
FREE(storedd);
FREE(repeat);
st_free_table(computed);
return(0);
}
repeat[index]--;
if (repeat[index] == 0) {
int *pointer = &STOREDD(index,0);
result = st_delete(computed, &pointer, NULL);
if (!result) {
FREE(storedd);
FREE(repeat);
st_free_table(computed);
return(0);
}
}
/* Copy the new individual to the entry of the
** population table just made available and update the
** computed table.
*/
for (n = 0; n <= numvars; n++) {
STOREDD(large,n) = STOREDD(i,n);
}
if (st_lookup_int(computed,(char *)&STOREDD(large,0),
&index)) {
repeat[index]++;
} else {
if (st_insert(computed,(char *)&STOREDD(large,0),
(char *)(long)large) == ST_OUT_OF_MEM) {
FREE(storedd);
FREE(repeat);
st_free_table(computed);
return(0);
}
repeat[large]++;
}
}
}
}
/* Find the smallest DD in the population and build it;
** that will be the result.
*/
small = find_best();
/* Print stats on the final population. */
#ifdef DD_STATS
average_fitness = find_average_fitness();
(void) fprintf(table->out,"\nFinal population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness);
#endif
/* Clean up, build the result DD, and return. */
st_free_table(computed);
computed = NULL;
result = build_dd(table,small,lower,upper);
FREE(storedd);
FREE(repeat);
return(result);
} /* end of cuddGa */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Generates the random sequences for the initial population.]
Description [Generates the random sequences for the initial population.
The sequences are permutations of the indices between lower and
upper in the current order.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
make_random(
DdManager * table,
int lower)
{
int i,j; /* loop variables */
int *used; /* is a number already in a permutation */
int next; /* next random number without repetitions */
used = ALLOC(int,numvars);
if (used == NULL) {
table->errorCode = CUDD_MEMORY_OUT;
return(0);
}
#if 0
#ifdef DD_STATS
(void) fprintf(table->out,"Initial population before sifting\n");
for (i = 0; i < 2; i++) {
for (j = 0; j < numvars; j++) {
(void) fprintf(table->out," %2d",STOREDD(i,j));
}
(void) fprintf(table->out,"\n");
}
#endif
#endif
for (i = 2; i < popsize; i++) {
for (j = 0; j < numvars; j++) {
used[j] = 0;
}
/* Generate a permutation of {0...numvars-1} and use it to
** permute the variables in the layesr from lower to upper.
*/
for (j = 0; j < numvars; j++) {
do {
next = rand_int(numvars-1);
} while (used[next] != 0);
used[next] = 1;
STOREDD(i,j) = table->invperm[next+lower];
}
#if 0
#ifdef DD_STATS
/* Print the order just generated. */
for (j = 0; j < numvars; j++) {
(void) fprintf(table->out," %2d",STOREDD(i,j));
}
(void) fprintf(table->out,"\n");
#endif
#endif
}
FREE(used);
return(1);
} /* end of make_random */
/**Function********************************************************************
Synopsis [Moves one variable up.]
Description [Takes a variable from position x and sifts it up to
position x_low; x_low should be less than x. Returns 1 if successful;
0 otherwise]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
sift_up(
DdManager * table,
int x,
int x_low)
{
int y;
int size;
y = cuddNextLow(table,x);
while (y >= x_low) {
size = cuddSwapInPlace(table,y,x);
if (size == 0) {
return(0);
}
x = y;
y = cuddNextLow(table,x);
}
return(1);
} /* end of sift_up */
/**Function********************************************************************
Synopsis [Builds a DD from a given order.]
Description [Builds a DD from a given order. This procedure also
sifts the final order and inserts into the array the size in nodes
of the result. Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
build_dd(
DdManager * table,
int num /* the index of the individual to be built */,
int lower,
int upper)
{
int i,j; /* loop vars */
int position;
int index;
int limit; /* how large the DD for this order can grow */
int size;
/* Check the computed table. If the order already exists, it
** suffices to copy the size from the existing entry.
*/
if (computed && st_lookup_int(computed,(char *)&STOREDD(num,0),&index)) {
STOREDD(num,numvars) = STOREDD(index,numvars);
#ifdef DD_STATS
(void) fprintf(table->out,"\nCache hit for index %d", index);
#endif
return(1);
}
/* Stop if the DD grows 20 times larges than the reference size. */
limit = 20 * STOREDD(0,numvars);
/* Sift up the variables so as to build the desired permutation.
** First the variable that has to be on top is sifted to the top.
** Then the variable that has to occupy the secon position is sifted
** up to the second position, and so on.
*/
for (j = 0; j < numvars; j++) {
i = STOREDD(num,j);
position = table->perm[i];
result = sift_up(table,position,j+lower);
if (!result) return(0);
size = table->keys - table->isolated;
if (size > limit) break;
}
/* Sift the DD just built. */
#ifdef DD_STATS
(void) fprintf(table->out,"\n");
#endif
result = cuddSifting(table,lower,upper);
if (!result) return(0);
/* Copy order and size to table. */
for (j = 0; j < numvars; j++) {
STOREDD(num,j) = table->invperm[lower+j];
}
STOREDD(num,numvars) = table->keys - table->isolated; /* size of new DD */
return(1);
} /* end of build_dd */
/**Function********************************************************************
Synopsis [Finds the largest DD in the population.]
Description [Finds the largest DD in the population. If an order is
repeated, it avoids choosing the copy that is in the computed table
(it has repeat[i] > 1).]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
largest(void)
{
int i; /* loop var */
int big; /* temporary holder to return result */
big = 0;
while (repeat[big] > 1) big++;
for (i = big + 1; i < popsize; i++) {
if (STOREDD(i,numvars) >= STOREDD(big,numvars) && repeat[i] <= 1) {
big = i;
}
}
return(big);
} /* end of largest */
/**Function********************************************************************
Synopsis [Generates a random number between 0 and the integer a.]
Description []
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
rand_int(
int a)
{
return(Cudd_Random() % (a+1));
} /* end of rand_int */
/**Function********************************************************************
Synopsis [Hash function for the computed table.]
Description [Hash function for the computed table. Returns the bucket
number.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
array_hash(
char * array,
int modulus)
{
int val = 0;
int i;
int *intarray;
intarray = (int *) array;
for (i = 0; i < numvars; i++) {
val = val * 997 + intarray[i];
}
return ((val < 0) ? -val : val) % modulus;
} /* end of array_hash */
/**Function********************************************************************
Synopsis [Comparison function for the computed table.]
Description [Comparison function for the computed table. Returns 0 if
the two arrays are equal; 1 otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
array_compare(
const char * array1,
const char * array2)
{
int i;
int *intarray1, *intarray2;
intarray1 = (int *) array1;
intarray2 = (int *) array2;
for (i = 0; i < numvars; i++) {
if (intarray1[i] != intarray2[i]) return(1);
}
return(0);
} /* end of array_compare */
/**Function********************************************************************
Synopsis [Returns the index of the fittest individual.]
Description []
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
find_best(void)
{
int i,small;
small = 0;
for (i = 1; i < popsize; i++) {
if (STOREDD(i,numvars) < STOREDD(small,numvars)) {
small = i;
}
}
return(small);
} /* end of find_best */
/**Function********************************************************************
Synopsis [Returns the average fitness of the population.]
Description []
SideEffects [None]
SeeAlso []
******************************************************************************/
#ifdef DD_STATS
static double
find_average_fitness(void)
{
int i;
int total_fitness = 0;
double average_fitness;
for (i = 0; i < popsize; i++) {
total_fitness += STOREDD(i,numvars);
}
average_fitness = (double) total_fitness / (double) popsize;
return(average_fitness);
} /* end of find_average_fitness */
#endif
/**Function********************************************************************
Synopsis [Performs the crossover between two parents.]
Description [Performs the crossover between two randomly chosen
parents, and creates two children, x1 and x2. Uses the Partially
Matched Crossover operator.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
PMX(
int maxvar)
{
int cut1,cut2; /* the two cut positions (random) */
int mom,dad; /* the two randomly chosen parents */
int *inv1; /* inverse permutations for repair algo */
int *inv2;
int i; /* loop vars */
int u,v; /* aux vars */
inv1 = ALLOC(int,maxvar);
if (inv1 == NULL) {
return(0);
}
inv2 = ALLOC(int,maxvar);
if (inv2 == NULL) {
FREE(inv1);
return(0);
}
/* Choose two orders from the population using roulette wheel. */
if (!roulette(&mom,&dad)) {
FREE(inv1);
FREE(inv2);
return(0);
}
/* Choose two random cut positions. A cut in position i means that
** the cut immediately precedes position i. If cut1 < cut2, we
** exchange the middle of the two orderings; otherwise, we
** exchange the beginnings and the ends.
*/
cut1 = rand_int(numvars-1);
do {
cut2 = rand_int(numvars-1);
} while (cut1 == cut2);
#if 0
/* Print out the parents. */
(void) fprintf(table->out,
"Crossover of %d (mom) and %d (dad) between %d and %d\n",
mom,dad,cut1,cut2);
for (i = 0; i < numvars; i++) {
if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
(void) fprintf(table->out,"%2d ",STOREDD(mom,i));
}
(void) fprintf(table->out,"\n");
for (i = 0; i < numvars; i++) {
if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
(void) fprintf(table->out,"%2d ",STOREDD(dad,i));
}
(void) fprintf(table->out,"\n");
#endif
/* Initialize the inverse permutations: -1 means yet undetermined. */
for (i = 0; i < maxvar; i++) {
inv1[i] = -1;
inv2[i] = -1;
}
/* Copy the portions whithin the cuts. */
for (i = cut1; i != cut2; i = (i == numvars-1) ? 0 : i+1) {
STOREDD(popsize,i) = STOREDD(dad,i);
inv1[STOREDD(popsize,i)] = i;
STOREDD(popsize+1,i) = STOREDD(mom,i);
inv2[STOREDD(popsize+1,i)] = i;
}
/* Now apply the repair algorithm outside the cuts. */
for (i = cut2; i != cut1; i = (i == numvars-1 ) ? 0 : i+1) {
v = i;
do {
u = STOREDD(mom,v);
v = inv1[u];
} while (v != -1);
STOREDD(popsize,i) = u;
inv1[u] = i;
v = i;
do {
u = STOREDD(dad,v);
v = inv2[u];
} while (v != -1);
STOREDD(popsize+1,i) = u;
inv2[u] = i;
}
#if 0
/* Print the results of crossover. */
for (i = 0; i < numvars; i++) {
if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
(void) fprintf(table->out,"%2d ",STOREDD(popsize,i));
}
(void) fprintf(table->out,"\n");
for (i = 0; i < numvars; i++) {
if (i == cut1 || i == cut2) (void) fprintf(table->out,"|");
(void) fprintf(table->out,"%2d ",STOREDD(popsize+1,i));
}
(void) fprintf(table->out,"\n");
#endif
FREE(inv1);
FREE(inv2);
return(1);
} /* end of PMX */
/**Function********************************************************************
Synopsis [Selects two parents with the roulette wheel method.]
Description [Selects two distinct parents with the roulette wheel method.]
SideEffects [The indices of the selected parents are returned as side
effects.]
SeeAlso []
******************************************************************************/
static int
roulette(
int * p1,
int * p2)
{
double *wheel;
double spin;
int i;
wheel = ALLOC(double,popsize);
if (wheel == NULL) {
return(0);
}
/* The fitness of an individual is the reciprocal of its size. */
wheel[0] = 1.0 / (double) STOREDD(0,numvars);
for (i = 1; i < popsize; i++) {
wheel[i] = wheel[i-1] + 1.0 / (double) STOREDD(i,numvars);
}
/* Get a random number between 0 and wheel[popsize-1] (that is,
** the sum of all fitness values. 2147483561 is the largest number
** returned by Cudd_Random.
*/
spin = wheel[numvars-1] * (double) Cudd_Random() / 2147483561.0;
/* Find the lucky element by scanning the wheel. */
for (i = 0; i < popsize; i++) {
if (spin <= wheel[i]) break;
}
*p1 = i;
/* Repeat the process for the second parent, making sure it is
** distinct from the first.
*/
do {
spin = wheel[popsize-1] * (double) Cudd_Random() / 2147483561.0;
for (i = 0; i < popsize; i++) {
if (spin <= wheel[i]) break;
}
} while (i == *p1);
*p2 = i;
FREE(wheel);
return(1);
} /* end of roulette */

2188
cudd_local/cudd/cuddGroup.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,568 @@
/**CFile***********************************************************************
FileName [cuddHarwell.c]
PackageName [cudd]
Synopsis [Function to read a matrix in Harwell format.]
Description [External procedures included in this module:
<ul>
<li> Cudd_addHarwell()
</ul>
]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddHarwell.c,v 1.10 2012/02/05 01:07:19 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Reads in a matrix in the format of the Harwell-Boeing
benchmark suite.]
Description [Reads in a matrix in the format of the Harwell-Boeing
benchmark suite. The variables are ordered as follows:
<blockquote>
x\[0\] y\[0\] x\[1\] y\[1\] ...
</blockquote>
0 is the most significant bit. On input, nx and ny hold the numbers
of row and column variables already in existence. On output, they
hold the numbers of row and column variables actually used by the
matrix. m and n are set to the numbers of rows and columns of the
matrix. Their values on input are immaterial. Returns 1 on
success; 0 otherwise. The ADD for the sparse matrix is returned in
E, and its reference count is > 0.]
SideEffects [None]
SeeAlso [Cudd_addRead Cudd_bddRead]
******************************************************************************/
int
Cudd_addHarwell(
FILE * fp /* pointer to the input file */,
DdManager * dd /* DD manager */,
DdNode ** E /* characteristic function of the graph */,
DdNode *** x /* array of row variables */,
DdNode *** y /* array of column variables */,
DdNode *** xn /* array of complemented row variables */,
DdNode *** yn_ /* array of complemented column variables */,
int * nx /* number or row variables */,
int * ny /* number or column variables */,
int * m /* number of rows */,
int * n /* number of columns */,
int bx /* first index of row variables */,
int sx /* step of row variables */,
int by /* first index of column variables */,
int sy /* step of column variables */,
int pr /* verbosity level */)
{
DdNode *one, *zero;
DdNode *w;
DdNode *cubex, *cubey, *minterm1;
int u, v, err, i, j, nv;
double val;
DdNode **lx, **ly, **lxn, **lyn; /* local copies of x, y, xn, yn_ */
int lnx, lny; /* local copies of nx and ny */
char title[73], key[9], mxtype[4], rhstyp[4];
int totcrd, ptrcrd, indcrd, valcrd, rhscrd,
nrow, ncol, nnzero, neltvl,
nrhs, nrhsix;
int *colptr, *rowind;
#if 0
int nguess, nexact;
int *rhsptr, *rhsind;
#endif
if (*nx < 0 || *ny < 0) return(0);
one = DD_ONE(dd);
zero = DD_ZERO(dd);
/* Read the header */
err = fscanf(fp, "%72c %8c", title, key);
if (err == EOF) {
return(0);
} else if (err != 2) {
return(0);
}
title[72] = (char) 0;
key[8] = (char) 0;
err = fscanf(fp, "%d %d %d %d %d", &totcrd, &ptrcrd, &indcrd,
&valcrd, &rhscrd);
if (err == EOF) {
return(0);
} else if (err != 5) {
return(0);
}
err = fscanf(fp, "%3s %d %d %d %d", mxtype, &nrow, &ncol,
&nnzero, &neltvl);
if (err == EOF) {
return(0);
} else if (err != 5) {
return(0);
}
/* Skip FORTRAN formats */
if (rhscrd == 0) {
err = fscanf(fp, "%*s %*s %*s \n");
} else {
err = fscanf(fp, "%*s %*s %*s %*s \n");
}
if (err == EOF) {
return(0);
} else if (err != 0) {
return(0);
}
/* Print out some stuff if requested to be verbose */
if (pr>0) {
(void) fprintf(dd->out,"%s: type %s, %d rows, %d columns, %d entries\n", key,
mxtype, nrow, ncol, nnzero);
if (pr>1) (void) fprintf(dd->out,"%s\n", title);
}
/* Check matrix type */
if (mxtype[0] != 'R' || mxtype[1] != 'U' || mxtype[2] != 'A') {
(void) fprintf(dd->err,"%s: Illegal matrix type: %s\n",
key, mxtype);
return(0);
}
if (neltvl != 0) return(0);
/* Read optional 5-th line */
if (rhscrd != 0) {
err = fscanf(fp, "%3c %d %d", rhstyp, &nrhs, &nrhsix);
if (err == EOF) {
return(0);
} else if (err != 3) {
return(0);
}
rhstyp[3] = (char) 0;
if (rhstyp[0] != 'F') {
(void) fprintf(dd->err,
"%s: Sparse right-hand side not yet supported\n", key);
return(0);
}
if (pr>0) (void) fprintf(dd->out,"%d right-hand side(s)\n", nrhs);
} else {
nrhs = 0;
}
/* Compute the number of variables */
/* row and column numbers start from 0 */
u = nrow - 1;
for (i=0; u > 0; i++) {
u >>= 1;
}
lnx = i;
if (nrhs == 0) {
v = ncol - 1;
} else {
v = 2* (ddMax(ncol, nrhs) - 1);
}
for (i=0; v > 0; i++) {
v >>= 1;
}
lny = i;
/* Allocate or reallocate arrays for variables as needed */
if (*nx == 0) {
if (lnx > 0) {
*x = lx = ALLOC(DdNode *,lnx);
if (lx == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
*xn = lxn = ALLOC(DdNode *,lnx);
if (lxn == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
} else {
*x = *xn = NULL;
}
} else if (lnx > *nx) {
*x = lx = REALLOC(DdNode *, *x, lnx);
if (lx == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
*xn = lxn = REALLOC(DdNode *, *xn, lnx);
if (lxn == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
} else {
lx = *x;
lxn = *xn;
}
if (*ny == 0) {
if (lny >0) {
*y = ly = ALLOC(DdNode *,lny);
if (ly == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
*yn_ = lyn = ALLOC(DdNode *,lny);
if (lyn == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
} else {
*y = *yn_ = NULL;
}
} else if (lny > *ny) {
*y = ly = REALLOC(DdNode *, *y, lny);
if (ly == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
*yn_ = lyn = REALLOC(DdNode *, *yn_, lny);
if (lyn == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
} else {
ly = *y;
lyn = *yn_;
}
/* Create new variables as needed */
for (i= *nx,nv=bx+(*nx)*sx; i < lnx; i++,nv+=sx) {
do {
dd->reordered = 0;
lx[i] = cuddUniqueInter(dd, nv, one, zero);
} while (dd->reordered == 1);
if (lx[i] == NULL) return(0);
cuddRef(lx[i]);
do {
dd->reordered = 0;
lxn[i] = cuddUniqueInter(dd, nv, zero, one);
} while (dd->reordered == 1);
if (lxn[i] == NULL) return(0);
cuddRef(lxn[i]);
}
for (i= *ny,nv=by+(*ny)*sy; i < lny; i++,nv+=sy) {
do {
dd->reordered = 0;
ly[i] = cuddUniqueInter(dd, nv, one, zero);
} while (dd->reordered == 1);
if (ly[i] == NULL) return(0);
cuddRef(ly[i]);
do {
dd->reordered = 0;
lyn[i] = cuddUniqueInter(dd, nv, zero, one);
} while (dd->reordered == 1);
if (lyn[i] == NULL) return(0);
cuddRef(lyn[i]);
}
/* Update matrix parameters */
*nx = lnx;
*ny = lny;
*m = nrow;
if (nrhs == 0) {
*n = ncol;
} else {
*n = (1 << (lny - 1)) + nrhs;
}
/* Read structure data */
colptr = ALLOC(int, ncol+1);
if (colptr == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
rowind = ALLOC(int, nnzero);
if (rowind == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
for (i=0; i<ncol+1; i++) {
err = fscanf(fp, " %d ", &u);
if (err == EOF){
FREE(colptr);
FREE(rowind);
return(0);
} else if (err != 1) {
FREE(colptr);
FREE(rowind);
return(0);
}
colptr[i] = u - 1;
}
if (colptr[0] != 0) {
(void) fprintf(dd->err,"%s: Unexpected colptr[0] (%d)\n",
key,colptr[0]);
FREE(colptr);
FREE(rowind);
return(0);
}
for (i=0; i<nnzero; i++) {
err = fscanf(fp, " %d ", &u);
if (err == EOF){
FREE(colptr);
FREE(rowind);
return(0);
} else if (err != 1) {
FREE(colptr);
FREE(rowind);
return(0);
}
rowind[i] = u - 1;
}
*E = zero; cuddRef(*E);
for (j=0; j<ncol; j++) {
v = j;
cubey = one; cuddRef(cubey);
for (nv = lny - 1; nv>=0; nv--) {
if (v & 1) {
w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]);
} else {
w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]);
}
if (w == NULL) {
Cudd_RecursiveDeref(dd, cubey);
FREE(colptr);
FREE(rowind);
return(0);
}
cuddRef(w);
Cudd_RecursiveDeref(dd, cubey);
cubey = w;
v >>= 1;
}
for (i=colptr[j]; i<colptr[j+1]; i++) {
u = rowind[i];
err = fscanf(fp, " %lf ", &val);
if (err == EOF || err != 1){
Cudd_RecursiveDeref(dd, cubey);
FREE(colptr);
FREE(rowind);
return(0);
}
/* Create new Constant node if necessary */
cubex = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) val);
if (cubex == NULL) {
Cudd_RecursiveDeref(dd, cubey);
FREE(colptr);
FREE(rowind);
return(0);
}
cuddRef(cubex);
for (nv = lnx - 1; nv>=0; nv--) {
if (u & 1) {
w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]);
} else {
w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]);
}
if (w == NULL) {
Cudd_RecursiveDeref(dd, cubey);
Cudd_RecursiveDeref(dd, cubex);
FREE(colptr);
FREE(rowind);
return(0);
}
cuddRef(w);
Cudd_RecursiveDeref(dd, cubex);
cubex = w;
u >>= 1;
}
minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex);
if (minterm1 == NULL) {
Cudd_RecursiveDeref(dd, cubey);
Cudd_RecursiveDeref(dd, cubex);
FREE(colptr);
FREE(rowind);
return(0);
}
cuddRef(minterm1);
Cudd_RecursiveDeref(dd, cubex);
w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1);
if (w == NULL) {
Cudd_RecursiveDeref(dd, cubey);
FREE(colptr);
FREE(rowind);
return(0);
}
cuddRef(w);
Cudd_RecursiveDeref(dd, minterm1);
Cudd_RecursiveDeref(dd, *E);
*E = w;
}
Cudd_RecursiveDeref(dd, cubey);
}
FREE(colptr);
FREE(rowind);
/* Read right-hand sides */
for (j=0; j<nrhs; j++) {
v = j + (1<< (lny-1));
cubey = one; cuddRef(cubey);
for (nv = lny - 1; nv>=0; nv--) {
if (v & 1) {
w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]);
} else {
w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]);
}
if (w == NULL) {
Cudd_RecursiveDeref(dd, cubey);
return(0);
}
cuddRef(w);
Cudd_RecursiveDeref(dd, cubey);
cubey = w;
v >>= 1;
}
for (i=0; i<nrow; i++) {
u = i;
err = fscanf(fp, " %lf ", &val);
if (err == EOF || err != 1){
Cudd_RecursiveDeref(dd, cubey);
return(0);
}
/* Create new Constant node if necessary */
if (val == (double) 0.0) continue;
cubex = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) val);
if (cubex == NULL) {
Cudd_RecursiveDeref(dd, cubey);
return(0);
}
cuddRef(cubex);
for (nv = lnx - 1; nv>=0; nv--) {
if (u & 1) {
w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]);
} else {
w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]);
}
if (w == NULL) {
Cudd_RecursiveDeref(dd, cubey);
Cudd_RecursiveDeref(dd, cubex);
return(0);
}
cuddRef(w);
Cudd_RecursiveDeref(dd, cubex);
cubex = w;
u >>= 1;
}
minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex);
if (minterm1 == NULL) {
Cudd_RecursiveDeref(dd, cubey);
Cudd_RecursiveDeref(dd, cubex);
return(0);
}
cuddRef(minterm1);
Cudd_RecursiveDeref(dd, cubex);
w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1);
if (w == NULL) {
Cudd_RecursiveDeref(dd, cubey);
return(0);
}
cuddRef(w);
Cudd_RecursiveDeref(dd, minterm1);
Cudd_RecursiveDeref(dd, *E);
*E = w;
}
Cudd_RecursiveDeref(dd, cubey);
}
return(1);
} /* end of Cudd_addHarwell */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/

308
cudd_local/cudd/cuddInit.c Normal file
View File

@@ -0,0 +1,308 @@
/**CFile***********************************************************************
FileName [cuddInit.c]
PackageName [cudd]
Synopsis [Functions to initialize and shut down the DD manager.]
Description [External procedures included in this module:
<ul>
<li> Cudd_Init()
<li> Cudd_Quit()
</ul>
Internal procedures included in this module:
<ul>
<li> cuddZddInitUniv()
<li> cuddZddFreeUniv()
</ul>
]
SeeAlso []
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddInit.c,v 1.34 2012/02/05 01:07:19 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Creates a new DD manager.]
Description [Creates a new DD manager, initializes the table, the
basic constants and the projection functions. If maxMemory is 0,
Cudd_Init decides suitable values for the maximum size of the cache
and for the limit for fast unique table growth based on the available
memory. Returns a pointer to the manager if successful; NULL
otherwise.]
SideEffects [None]
SeeAlso [Cudd_Quit]
******************************************************************************/
DdManager *
Cudd_Init(
unsigned int numVars /* initial number of BDD variables (i.e., subtables) */,
unsigned int numVarsZ /* initial number of ZDD variables (i.e., subtables) */,
unsigned int numSlots /* initial size of the unique tables */,
unsigned int cacheSize /* initial size of the cache */,
unsigned long maxMemory /* target maximum memory occupation */)
{
DdManager *unique;
int i,result;
DdNode *one, *zero;
unsigned int maxCacheSize;
unsigned int looseUpTo;
extern DD_OOMFP MMoutOfMemory;
DD_OOMFP saveHandler;
if (maxMemory == 0) {
maxMemory = getSoftDataLimit();
}
looseUpTo = (unsigned int) ((maxMemory / sizeof(DdNode)) /
DD_MAX_LOOSE_FRACTION);
unique = cuddInitTable(numVars,numVarsZ,numSlots,looseUpTo);
if (unique == NULL) return(NULL);
unique->maxmem = (unsigned long) maxMemory / 10 * 9;
maxCacheSize = (unsigned int) ((maxMemory / sizeof(DdCache)) /
DD_MAX_CACHE_FRACTION);
result = cuddInitCache(unique,cacheSize,maxCacheSize);
if (result == 0) return(NULL);
saveHandler = MMoutOfMemory;
MMoutOfMemory = Cudd_OutOfMem;
unique->stash = ALLOC(char,(maxMemory / DD_STASH_FRACTION) + 4);
MMoutOfMemory = saveHandler;
if (unique->stash == NULL) {
(void) fprintf(unique->err,"Unable to set aside memory\n");
}
/* Initialize constants. */
unique->one = cuddUniqueConst(unique,1.0);
if (unique->one == NULL) return(0);
cuddRef(unique->one);
unique->zero = cuddUniqueConst(unique,0.0);
if (unique->zero == NULL) return(0);
cuddRef(unique->zero);
#ifdef HAVE_IEEE_754
if (DD_PLUS_INF_VAL != DD_PLUS_INF_VAL * 3 ||
DD_PLUS_INF_VAL != DD_PLUS_INF_VAL / 3) {
(void) fprintf(unique->err,"Warning: Crippled infinite values\n");
(void) fprintf(unique->err,"Recompile without -DHAVE_IEEE_754\n");
}
#endif
unique->plusinfinity = cuddUniqueConst(unique,DD_PLUS_INF_VAL);
if (unique->plusinfinity == NULL) return(0);
cuddRef(unique->plusinfinity);
unique->minusinfinity = cuddUniqueConst(unique,DD_MINUS_INF_VAL);
if (unique->minusinfinity == NULL) return(0);
cuddRef(unique->minusinfinity);
unique->background = unique->zero;
/* The logical zero is different from the CUDD_VALUE_TYPE zero! */
one = unique->one;
zero = Cudd_Not(one);
/* Create the projection functions. */
unique->vars = ALLOC(DdNodePtr,unique->maxSize);
if (unique->vars == NULL) {
unique->errorCode = CUDD_MEMORY_OUT;
return(NULL);
}
for (i = 0; i < unique->size; i++) {
unique->vars[i] = cuddUniqueInter(unique,i,one,zero);
if (unique->vars[i] == NULL) return(0);
cuddRef(unique->vars[i]);
}
if (unique->sizeZ)
cuddZddInitUniv(unique);
unique->memused += sizeof(DdNode *) * unique->maxSize;
return(unique);
} /* end of Cudd_Init */
/**Function********************************************************************
Synopsis [Deletes resources associated with a DD manager.]
Description [Deletes resources associated with a DD manager and
resets the global statistical counters. (Otherwise, another manaqger
subsequently created would inherit the stats of this one.)]
SideEffects [None]
SeeAlso [Cudd_Init]
******************************************************************************/
void
Cudd_Quit(
DdManager * unique)
{
if (unique->stash != NULL) FREE(unique->stash);
cuddFreeTable(unique);
} /* end of Cudd_Quit */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Initializes the ZDD universe.]
Description [Initializes the ZDD universe. Returns 1 if successful; 0
otherwise.]
SideEffects [None]
SeeAlso [cuddZddFreeUniv]
******************************************************************************/
int
cuddZddInitUniv(
DdManager * zdd)
{
DdNode *p, *res;
int i;
zdd->univ = ALLOC(DdNodePtr, zdd->sizeZ);
if (zdd->univ == NULL) {
zdd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
res = DD_ONE(zdd);
cuddRef(res);
for (i = zdd->sizeZ - 1; i >= 0; i--) {
unsigned int index = zdd->invpermZ[i];
p = res;
res = cuddUniqueInterZdd(zdd, index, p, p);
if (res == NULL) {
Cudd_RecursiveDerefZdd(zdd,p);
FREE(zdd->univ);
return(0);
}
cuddRef(res);
cuddDeref(p);
zdd->univ[i] = res;
}
#ifdef DD_VERBOSE
cuddZddP(zdd, zdd->univ[0]);
#endif
return(1);
} /* end of cuddZddInitUniv */
/**Function********************************************************************
Synopsis [Frees the ZDD universe.]
Description [Frees the ZDD universe.]
SideEffects [None]
SeeAlso [cuddZddInitUniv]
******************************************************************************/
void
cuddZddFreeUniv(
DdManager * zdd)
{
if (zdd->univ) {
Cudd_RecursiveDerefZdd(zdd, zdd->univ[0]);
FREE(zdd->univ);
}
} /* end of cuddZddFreeUniv */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/

1188
cudd_local/cudd/cuddInt.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,432 @@
/**CFile***********************************************************************
FileName [cuddInteract.c]
PackageName [cudd]
Synopsis [Functions to manipulate the variable interaction matrix.]
Description [Internal procedures included in this file:
<ul>
<li> cuddSetInteract()
<li> cuddTestInteract()
<li> cuddInitInteract()
</ul>
Static procedures included in this file:
<ul>
<li> ddSuppInteract()
<li> ddClearLocal()
<li> ddUpdateInteract()
<li> ddClearGlobal()
</ul>
The interaction matrix tells whether two variables are
both in the support of some function of the DD. The main use of the
interaction matrix is in the in-place swapping. Indeed, if two
variables do not interact, there is no arc connecting the two layers;
therefore, the swap can be performed in constant time, without
scanning the subtables. Another use of the interaction matrix is in
the computation of the lower bounds for sifting. Finally, the
interaction matrix can be used to speed up aggregation checks in
symmetric and group sifting.<p>
The computation of the interaction matrix is done with a series of
depth-first searches. The searches start from those nodes that have
only external references. The matrix is stored as a packed array of bits;
since it is symmetric, only the upper triangle is kept in memory.
As a final remark, we note that there may be variables that do
interact, but that for a given variable order have no arc connecting
their layers when they are adjacent. For instance, in ite(a,b,c) with
the order a<b<c, b and c interact, but are not connected.]
SeeAlso []
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
#if SIZEOF_LONG == 8
#define BPL 64
#define LOGBPL 6
#else
#define BPL 32
#define LOGBPL 5
#endif
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddInteract.c,v 1.14 2012/02/05 01:07:19 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static void ddSuppInteract (DdNode *f, char *support);
static void ddClearLocal (DdNode *f);
static void ddUpdateInteract (DdManager *table, char *support);
static void ddClearGlobal (DdManager *table);
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Set interaction matrix entries.]
Description [Given a pair of variables 0 <= x < y < table->size,
sets the corresponding bit of the interaction matrix to 1.]
SideEffects [None]
SeeAlso []
******************************************************************************/
void
cuddSetInteract(
DdManager * table,
int x,
int y)
{
int posn, word, bit;
#ifdef DD_DEBUG
assert(x < y);
assert(y < table->size);
assert(x >= 0);
#endif
posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1;
word = posn >> LOGBPL;
bit = posn & (BPL-1);
table->interact[word] |= 1L << bit;
} /* end of cuddSetInteract */
/**Function********************************************************************
Synopsis [Test interaction matrix entries.]
Description [Given a pair of variables 0 <= x < y < table->size,
tests whether the corresponding bit of the interaction matrix is 1.
Returns the value of the bit.]
SideEffects [None]
SeeAlso []
******************************************************************************/
int
cuddTestInteract(
DdManager * table,
int x,
int y)
{
int posn, word, bit, result;
if (x > y) {
int tmp = x;
x = y;
y = tmp;
}
#ifdef DD_DEBUG
assert(x < y);
assert(y < table->size);
assert(x >= 0);
#endif
posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1;
word = posn >> LOGBPL;
bit = posn & (BPL-1);
result = (table->interact[word] >> bit) & 1L;
return(result);
} /* end of cuddTestInteract */
/**Function********************************************************************
Synopsis [Initializes the interaction matrix.]
Description [Initializes the interaction matrix. The interaction
matrix is implemented as a bit vector storing the upper triangle of
the symmetric interaction matrix. The bit vector is kept in an array
of long integers. The computation is based on a series of depth-first
searches, one for each root of the DAG. Two flags are needed: The
local visited flag uses the LSB of the then pointer. The global
visited flag uses the LSB of the next pointer.
Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
int
cuddInitInteract(
DdManager * table)
{
int i,j;
unsigned long words;
long *interact;
char *support;
DdNode *f;
DdNode *sentinel = &(table->sentinel);
DdNodePtr *nodelist;
int slots;
unsigned long n = (unsigned long) table->size;
words = ((n * (n-1)) >> (1 + LOGBPL)) + 1;
table->interact = interact = ALLOC(long,words);
if (interact == NULL) {
table->errorCode = CUDD_MEMORY_OUT;
return(0);
}
for (i = 0; i < words; i++) {
interact[i] = 0;
}
support = ALLOC(char,n);
if (support == NULL) {
table->errorCode = CUDD_MEMORY_OUT;
FREE(interact);
return(0);
}
for (i = 0; i < n; i++) {
support[i] = 0;
}
for (i = 0; i < n; i++) {
nodelist = table->subtables[i].nodelist;
slots = table->subtables[i].slots;
for (j = 0; j < slots; j++) {
f = nodelist[j];
while (f != sentinel) {
/* A node is a root of the DAG if it cannot be
** reached by nodes above it. If a node was never
** reached during the previous depth-first searches,
** then it is a root, and we start a new depth-first
** search from it.
*/
if (!Cudd_IsComplement(f->next)) {
ddSuppInteract(f,support);
ddClearLocal(f);
ddUpdateInteract(table,support);
}
f = Cudd_Regular(f->next);
}
}
}
ddClearGlobal(table);
FREE(support);
return(1);
} /* end of cuddInitInteract */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Find the support of f.]
Description [Performs a DFS from f. Uses the LSB of the then pointer
as visited flag.]
SideEffects [Accumulates in support the variables on which f depends.]
SeeAlso []
******************************************************************************/
static void
ddSuppInteract(
DdNode * f,
char * support)
{
if (cuddIsConstant(f) || Cudd_IsComplement(cuddT(f))) {
return;
}
support[f->index] = 1;
ddSuppInteract(cuddT(f),support);
ddSuppInteract(Cudd_Regular(cuddE(f)),support);
/* mark as visited */
cuddT(f) = Cudd_Complement(cuddT(f));
f->next = Cudd_Complement(f->next);
return;
} /* end of ddSuppInteract */
/**Function********************************************************************
Synopsis [Performs a DFS from f, clearing the LSB of the then pointers.]
Description []
SideEffects [None]
SeeAlso []
******************************************************************************/
static void
ddClearLocal(
DdNode * f)
{
if (cuddIsConstant(f) || !Cudd_IsComplement(cuddT(f))) {
return;
}
/* clear visited flag */
cuddT(f) = Cudd_Regular(cuddT(f));
ddClearLocal(cuddT(f));
ddClearLocal(Cudd_Regular(cuddE(f)));
return;
} /* end of ddClearLocal */
/**Function********************************************************************
Synopsis [Marks as interacting all pairs of variables that appear in
support.]
Description [If support[i] == support[j] == 1, sets the (i,j) entry
of the interaction matrix to 1.]
SideEffects [Clears support.]
SeeAlso []
******************************************************************************/
static void
ddUpdateInteract(
DdManager * table,
char * support)
{
int i,j;
int n = table->size;
for (i = 0; i < n-1; i++) {
if (support[i] == 1) {
support[i] = 0;
for (j = i+1; j < n; j++) {
if (support[j] == 1) {
cuddSetInteract(table,i,j);
}
}
}
}
support[n-1] = 0;
} /* end of ddUpdateInteract */
/**Function********************************************************************
Synopsis [Scans the DD and clears the LSB of the next pointers.]
Description [The LSB of the next pointers are used as markers to tell
whether a node was reached by at least one DFS. Once the interaction
matrix is built, these flags are reset.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static void
ddClearGlobal(
DdManager * table)
{
int i,j;
DdNode *f;
DdNode *sentinel = &(table->sentinel);
DdNodePtr *nodelist;
int slots;
for (i = 0; i < table->size; i++) {
nodelist = table->subtables[i].nodelist;
slots = table->subtables[i].slots;
for (j = 0; j < slots; j++) {
f = nodelist[j];
while (f != sentinel) {
f->next = Cudd_Regular(f->next);
f = f->next;
}
}
}
} /* end of ddClearGlobal */

1557
cudd_local/cudd/cuddLCache.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,583 @@
/**CFile***********************************************************************
FileName [cuddLevelQ.c]
PackageName [cudd]
Synopsis [Procedure to manage level queues.]
Description [The functions in this file allow an application to
easily manipulate a queue where nodes are prioritized by level. The
emphasis is on efficiency. Therefore, the queue items can have
variable size. If the application does not need to attach
information to the nodes, it can declare the queue items to be of
type DdQueueItem. Otherwise, it can declare them to be of a
structure type such that the first three fields are data
pointers. The third pointer points to the node. The first two
pointers are used by the level queue functions. The remaining fields
are initialized to 0 when a new item is created, and are then left
to the exclusive use of the application. On the DEC Alphas the three
pointers must be 32-bit pointers when CUDD is compiled with 32-bit
pointers. The level queue functions make sure that each node
appears at most once in the queue. They do so by keeping a hash
table where the node is used as key. Queue items are recycled via a
free list for efficiency.
Internal procedures provided by this module:
<ul>
<li> cuddLevelQueueInit()
<li> cuddLevelQueueQuit()
<li> cuddLevelQueueEnqueue()
<li> cuddLevelQueueDequeue()
</ul>
Static procedures included in this module:
<ul>
<li> hashLookup()
<li> hashInsert()
<li> hashDelete()
<li> hashResize()
</ul>
]
SeeAlso []
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddLevelQ.c,v 1.16 2012/02/05 01:07:19 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**Macro***********************************************************************
Synopsis [Hash function for the table of a level queue.]
Description [Hash function for the table of a level queue.]
SideEffects [None]
SeeAlso [hashInsert hashLookup hashDelete]
******************************************************************************/
#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
#define lqHash(key,shift) \
(((unsigned)(ptruint)(key) * DD_P1) >> (shift))
#else
#define lqHash(key,shift) \
(((unsigned)(key) * DD_P1) >> (shift))
#endif
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static DdQueueItem * hashLookup(DdLevelQueue *queue, void *key);
static int hashInsert(DdLevelQueue *queue, DdQueueItem *item);
static void hashDelete(DdLevelQueue *queue, DdQueueItem *item);
static int hashResize(DdLevelQueue *queue);
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Initializes a level queue.]
Description [Initializes a level queue. A level queue is a queue
where inserts are based on the levels of the nodes. Within each
level the policy is FIFO. Level queues are useful in traversing a
BDD top-down. Queue items are kept in a free list when dequeued for
efficiency. Returns a pointer to the new queue if successful; NULL
otherwise.]
SideEffects [None]
SeeAlso [cuddLevelQueueQuit cuddLevelQueueEnqueue cuddLevelQueueDequeue]
******************************************************************************/
DdLevelQueue *
cuddLevelQueueInit(
int levels /* number of levels */,
int itemSize /* size of the item */,
int numBuckets /* initial number of hash buckets */)
{
DdLevelQueue *queue;
int logSize;
queue = ALLOC(DdLevelQueue,1);
if (queue == NULL)
return(NULL);
/* Keep pointers to the insertion points for all levels. */
queue->last = ALLOC(DdQueueItem *, levels);
if (queue->last == NULL) {
FREE(queue);
return(NULL);
}
/* Use a hash table to test for uniqueness. */
if (numBuckets < 2) numBuckets = 2;
logSize = cuddComputeFloorLog2(numBuckets);
queue->numBuckets = 1 << logSize;
queue->shift = sizeof(int) * 8 - logSize;
queue->buckets = ALLOC(DdQueueItem *, queue->numBuckets);
if (queue->buckets == NULL) {
FREE(queue->last);
FREE(queue);
return(NULL);
}
memset(queue->last, 0, levels * sizeof(DdQueueItem *));
memset(queue->buckets, 0, queue->numBuckets * sizeof(DdQueueItem *));
queue->first = NULL;
queue->freelist = NULL;
queue->levels = levels;
queue->itemsize = itemSize;
queue->size = 0;
queue->maxsize = queue->numBuckets * DD_MAX_SUBTABLE_DENSITY;
return(queue);
} /* end of cuddLevelQueueInit */
/**Function********************************************************************
Synopsis [Shuts down a level queue.]
Description [Shuts down a level queue and releases all the
associated memory.]
SideEffects [None]
SeeAlso [cuddLevelQueueInit]
******************************************************************************/
void
cuddLevelQueueQuit(
DdLevelQueue * queue)
{
DdQueueItem *item;
while (queue->freelist != NULL) {
item = queue->freelist;
queue->freelist = item->next;
FREE(item);
}
while (queue->first != NULL) {
item = (DdQueueItem *) queue->first;
queue->first = item->next;
FREE(item);
}
FREE(queue->buckets);
FREE(queue->last);
FREE(queue);
return;
} /* end of cuddLevelQueueQuit */
/**Function********************************************************************
Synopsis [Inserts a new key in a level queue.]
Description [Inserts a new key in a level queue. A new entry is
created in the queue only if the node is not already
enqueued. Returns a pointer to the queue item if successful; NULL
otherwise.]
SideEffects [None]
SeeAlso [cuddLevelQueueInit cuddLevelQueueDequeue]
******************************************************************************/
void *
cuddLevelQueueEnqueue(
DdLevelQueue * queue /* level queue */,
void * key /* key to be enqueued */,
int level /* level at which to insert */)
{
DdQueueItem *item;
#ifdef DD_DEBUG
assert(level < queue->levels);
#endif
/* Check whether entry for this node exists. */
item = hashLookup(queue,key);
if (item != NULL) return(item);
/* Get a free item from either the free list or the memory manager. */
if (queue->freelist == NULL) {
item = (DdQueueItem *) ALLOC(char, queue->itemsize);
if (item == NULL)
return(NULL);
} else {
item = queue->freelist;
queue->freelist = item->next;
}
/* Initialize. */
memset(item, 0, queue->itemsize);
item->key = key;
/* Update stats. */
queue->size++;
if (queue->last[level]) {
/* There are already items for this level in the queue. */
item->next = queue->last[level]->next;
queue->last[level]->next = item;
} else {
/* There are no items at the current level. Look for the first
** non-empty level preceeding this one. */
int plevel = level;
while (plevel != 0 && queue->last[plevel] == NULL)
plevel--;
if (queue->last[plevel] == NULL) {
/* No element precedes this one in the queue. */
item->next = (DdQueueItem *) queue->first;
queue->first = item;
} else {
item->next = queue->last[plevel]->next;
queue->last[plevel]->next = item;
}
}
queue->last[level] = item;
/* Insert entry for the key in the hash table. */
if (hashInsert(queue,item) == 0) {
return(NULL);
}
return(item);
} /* end of cuddLevelQueueEnqueue */
/**Function********************************************************************
Synopsis [Inserts the first key in a level queue.]
Description [Inserts the first key in a level queue. Returns a
pointer to the queue item if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [cuddLevelQueueEnqueue]
******************************************************************************/
void *
cuddLevelQueueFirst(
DdLevelQueue * queue /* level queue */,
void * key /* key to be enqueued */,
int level /* level at which to insert */)
{
DdQueueItem *item;
#ifdef DD_DEBUG
assert(level < queue->levels);
/* Check whether entry for this node exists. */
item = hashLookup(queue,key);
assert(item == NULL);
#endif
/* Get a free item from either the free list or the memory manager. */
if (queue->freelist == NULL) {
item = (DdQueueItem *) ALLOC(char, queue->itemsize);
if (item == NULL)
return(NULL);
} else {
item = queue->freelist;
queue->freelist = item->next;
}
/* Initialize. */
memset(item, 0, queue->itemsize);
item->key = key;
/* Update stats. */
queue->size = 1;
/* No element precedes this one in the queue. */
queue->first = item;
queue->last[level] = item;
/* Insert entry for the key in the hash table. */
if (hashInsert(queue,item) == 0) {
return(NULL);
}
return(item);
} /* end of cuddLevelQueueFirst */
/**Function********************************************************************
Synopsis [Remove an item from the front of a level queue.]
Description [Remove an item from the front of a level queue.]
SideEffects [None]
SeeAlso [cuddLevelQueueEnqueue]
******************************************************************************/
void
cuddLevelQueueDequeue(
DdLevelQueue * queue,
int level)
{
DdQueueItem *item = (DdQueueItem *) queue->first;
/* Delete from the hash table. */
hashDelete(queue,item);
/* Since we delete from the front, if this is the last item for
** its level, there are no other items for the same level. */
if (queue->last[level] == item) {
queue->last[level] = NULL;
}
queue->first = item->next;
/* Put item on the free list. */
item->next = queue->freelist;
queue->freelist = item;
/* Update stats. */
queue->size--;
return;
} /* end of cuddLevelQueueDequeue */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Looks up a key in the hash table of a level queue.]
Description [Looks up a key in the hash table of a level queue. Returns
a pointer to the item with the given key if the key is found; NULL
otherwise.]
SideEffects [None]
SeeAlso [cuddLevelQueueEnqueue hashInsert]
******************************************************************************/
static DdQueueItem *
hashLookup(
DdLevelQueue * queue,
void * key)
{
int posn;
DdQueueItem *item;
posn = lqHash(key,queue->shift);
item = queue->buckets[posn];
while (item != NULL) {
if (item->key == key) {
return(item);
}
item = item->cnext;
}
return(NULL);
} /* end of hashLookup */
/**Function********************************************************************
Synopsis [Inserts an item in the hash table of a level queue.]
Description [Inserts an item in the hash table of a level queue. Returns
1 if successful; 0 otherwise. No check is performed to see if an item with
the same key is already in the hash table.]
SideEffects [None]
SeeAlso [cuddLevelQueueEnqueue]
******************************************************************************/
static int
hashInsert(
DdLevelQueue * queue,
DdQueueItem * item)
{
int result;
int posn;
if (queue->size > queue->maxsize) {
result = hashResize(queue);
if (result == 0) return(0);
}
posn = lqHash(item->key,queue->shift);
item->cnext = queue->buckets[posn];
queue->buckets[posn] = item;
return(1);
} /* end of hashInsert */
/**Function********************************************************************
Synopsis [Removes an item from the hash table of a level queue.]
Description [Removes an item from the hash table of a level queue.
Nothing is done if the item is not in the table.]
SideEffects [None]
SeeAlso [cuddLevelQueueDequeue hashInsert]
******************************************************************************/
static void
hashDelete(
DdLevelQueue * queue,
DdQueueItem * item)
{
int posn;
DdQueueItem *prevItem;
posn = lqHash(item->key,queue->shift);
prevItem = queue->buckets[posn];
if (prevItem == NULL) return;
if (prevItem == item) {
queue->buckets[posn] = prevItem->cnext;
return;
}
while (prevItem->cnext != NULL) {
if (prevItem->cnext == item) {
prevItem->cnext = item->cnext;
return;
}
prevItem = prevItem->cnext;
}
return;
} /* end of hashDelete */
/**Function********************************************************************
Synopsis [Resizes the hash table of a level queue.]
Description [Resizes the hash table of a level queue. Returns 1 if
successful; 0 otherwise.]
SideEffects [None]
SeeAlso [hashInsert]
******************************************************************************/
static int
hashResize(
DdLevelQueue * queue)
{
int j;
int posn;
DdQueueItem *item;
DdQueueItem *next;
int numBuckets;
DdQueueItem **buckets;
DdQueueItem **oldBuckets = queue->buckets;
int shift;
int oldNumBuckets = queue->numBuckets;
extern DD_OOMFP MMoutOfMemory;
DD_OOMFP saveHandler;
/* Compute the new size of the subtable. */
numBuckets = oldNumBuckets << 1;
saveHandler = MMoutOfMemory;
MMoutOfMemory = Cudd_OutOfMem;
buckets = queue->buckets = ALLOC(DdQueueItem *, numBuckets);
MMoutOfMemory = saveHandler;
if (buckets == NULL) {
queue->maxsize <<= 1;
return(1);
}
queue->numBuckets = numBuckets;
shift = --(queue->shift);
queue->maxsize <<= 1;
memset(buckets, 0, numBuckets * sizeof(DdQueueItem *));
for (j = 0; j < oldNumBuckets; j++) {
item = oldBuckets[j];
while (item != NULL) {
next = item->cnext;
posn = lqHash(item->key, shift);
item->cnext = buckets[posn];
buckets[posn] = item;
item = next;
}
}
FREE(oldBuckets);
return(1);
} /* end of hashResize */

1365
cudd_local/cudd/cuddLinear.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,264 @@
/**CFile***********************************************************************
FileName [cuddLiteral.c]
PackageName [cudd]
Synopsis [Functions for manipulation of literal sets represented by
BDDs.]
Description [External procedures included in this file:
<ul>
<li> Cudd_bddLiteralSetIntersection()
</ul>
Internal procedures included in this file:
<ul>
<li> cuddBddLiteralSetIntersectionRecur()
</ul>]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddLiteral.c,v 1.9 2012/02/05 01:07:19 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Computes the intesection of two sets of literals
represented as BDDs.]
Description [Computes the intesection of two sets of literals
represented as BDDs. Each set is represented as a cube of the
literals in the set. The empty set is represented by the constant 1.
No variable can be simultaneously present in both phases in a set.
Returns a pointer to the BDD representing the intersected sets, if
successful; NULL otherwise.]
SideEffects [None]
******************************************************************************/
DdNode *
Cudd_bddLiteralSetIntersection(
DdManager * dd,
DdNode * f,
DdNode * g)
{
DdNode *res;
do {
dd->reordered = 0;
res = cuddBddLiteralSetIntersectionRecur(dd,f,g);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_bddLiteralSetIntersection */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Performs the recursive step of
Cudd_bddLiteralSetIntersection.]
Description [Performs the recursive step of
Cudd_bddLiteralSetIntersection. Scans the cubes for common variables,
and checks whether they agree in phase. Returns a pointer to the
resulting cube if successful; NULL otherwise.]
SideEffects [None]
******************************************************************************/
DdNode *
cuddBddLiteralSetIntersectionRecur(
DdManager * dd,
DdNode * f,
DdNode * g)
{
DdNode *res, *tmp;
DdNode *F, *G;
DdNode *fc, *gc;
DdNode *one;
DdNode *zero;
unsigned int topf, topg, comple;
int phasef, phaseg;
statLine(dd);
if (f == g) return(f);
F = Cudd_Regular(f);
G = Cudd_Regular(g);
one = DD_ONE(dd);
/* Here f != g. If F == G, then f and g are complementary.
** Since they are two cubes, this case only occurs when f == v,
** g == v', and v is a variable or its complement.
*/
if (F == G) return(one);
zero = Cudd_Not(one);
topf = cuddI(dd,F->index);
topg = cuddI(dd,G->index);
/* Look for a variable common to both cubes. If there are none, this
** loop will stop when the constant node is reached in both cubes.
*/
while (topf != topg) {
if (topf < topg) { /* move down on f */
comple = f != F;
f = cuddT(F);
if (comple) f = Cudd_Not(f);
if (f == zero) {
f = cuddE(F);
if (comple) f = Cudd_Not(f);
}
F = Cudd_Regular(f);
topf = cuddI(dd,F->index);
} else if (topg < topf) {
comple = g != G;
g = cuddT(G);
if (comple) g = Cudd_Not(g);
if (g == zero) {
g = cuddE(G);
if (comple) g = Cudd_Not(g);
}
G = Cudd_Regular(g);
topg = cuddI(dd,G->index);
}
}
/* At this point, f == one <=> g == 1. It suffices to test one of them. */
if (f == one) return(one);
res = cuddCacheLookup2(dd,Cudd_bddLiteralSetIntersection,f,g);
if (res != NULL) {
return(res);
}
/* Here f and g are both non constant and have the same top variable. */
comple = f != F;
fc = cuddT(F);
phasef = 1;
if (comple) fc = Cudd_Not(fc);
if (fc == zero) {
fc = cuddE(F);
phasef = 0;
if (comple) fc = Cudd_Not(fc);
}
comple = g != G;
gc = cuddT(G);
phaseg = 1;
if (comple) gc = Cudd_Not(gc);
if (gc == zero) {
gc = cuddE(G);
phaseg = 0;
if (comple) gc = Cudd_Not(gc);
}
tmp = cuddBddLiteralSetIntersectionRecur(dd,fc,gc);
if (tmp == NULL) {
return(NULL);
}
if (phasef != phaseg) {
res = tmp;
} else {
cuddRef(tmp);
if (phasef == 0) {
res = cuddBddAndRecur(dd,Cudd_Not(dd->vars[F->index]),tmp);
} else {
res = cuddBddAndRecur(dd,dd->vars[F->index],tmp);
}
if (res == NULL) {
Cudd_RecursiveDeref(dd,tmp);
return(NULL);
}
cuddDeref(tmp); /* Just cuddDeref, because it is included in result */
}
cuddCacheInsert2(dd,Cudd_bddLiteralSetIntersection,f,g,res);
return(res);
} /* end of cuddBddLiteralSetIntersectionRecur */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/

View File

@@ -0,0 +1,707 @@
/**CFile***********************************************************************
FileName [cuddMatMult.c]
PackageName [cudd]
Synopsis [Matrix multiplication functions.]
Description [External procedures included in this module:
<ul>
<li> Cudd_addMatrixMultiply()
<li> Cudd_addTimesPlus()
<li> Cudd_addTriangle()
<li> Cudd_addOuterSum()
</ul>
Static procedures included in this module:
<ul>
<li> addMMRecur()
<li> addTriangleRecur()
<li> cuddAddOuterSumRecur()
</ul>]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddMatMult.c,v 1.18 2012/02/05 01:07:19 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static DdNode * addMMRecur (DdManager *dd, DdNode *A, DdNode *B, int topP, int *vars);
static DdNode * addTriangleRecur (DdManager *dd, DdNode *f, DdNode *g, int *vars, DdNode *cube);
static DdNode * cuddAddOuterSumRecur (DdManager *dd, DdNode *M, DdNode *r, DdNode *c);
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Calculates the product of two matrices represented as
ADDs.]
Description [Calculates the product of two matrices, A and B,
represented as ADDs. This procedure implements the quasiring multiplication
algorithm. A is assumed to depend on variables x (rows) and z
(columns). B is assumed to depend on variables z (rows) and y
(columns). The product of A and B then depends on x (rows) and y
(columns). Only the z variables have to be explicitly identified;
they are the "summation" variables. Returns a pointer to the
result if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_addTimesPlus Cudd_addTriangle Cudd_bddAndAbstract]
******************************************************************************/
DdNode *
Cudd_addMatrixMultiply(
DdManager * dd,
DdNode * A,
DdNode * B,
DdNode ** z,
int nz)
{
int i, nvars, *vars;
DdNode *res;
/* Array vars says what variables are "summation" variables. */
nvars = dd->size;
vars = ALLOC(int,nvars);
if (vars == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(NULL);
}
for (i = 0; i < nvars; i++) {
vars[i] = 0;
}
for (i = 0; i < nz; i++) {
vars[z[i]->index] = 1;
}
do {
dd->reordered = 0;
res = addMMRecur(dd,A,B,-1,vars);
} while (dd->reordered == 1);
FREE(vars);
return(res);
} /* end of Cudd_addMatrixMultiply */
/**Function********************************************************************
Synopsis [Calculates the product of two matrices represented as
ADDs.]
Description [Calculates the product of two matrices, A and B,
represented as ADDs, using the CMU matrix by matrix multiplication
procedure by Clarke et al.. Matrix A has x's as row variables and z's
as column variables, while matrix B has z's as row variables and y's
as column variables. Returns the pointer to the result if successful;
NULL otherwise. The resulting matrix has x's as row variables and y's
as column variables.]
SideEffects [None]
SeeAlso [Cudd_addMatrixMultiply]
******************************************************************************/
DdNode *
Cudd_addTimesPlus(
DdManager * dd,
DdNode * A,
DdNode * B,
DdNode ** z,
int nz)
{
DdNode *w, *cube, *tmp, *res;
int i;
tmp = Cudd_addApply(dd,Cudd_addTimes,A,B);
if (tmp == NULL) return(NULL);
Cudd_Ref(tmp);
Cudd_Ref(cube = DD_ONE(dd));
for (i = nz-1; i >= 0; i--) {
w = Cudd_addIte(dd,z[i],cube,DD_ZERO(dd));
if (w == NULL) {
Cudd_RecursiveDeref(dd,tmp);
return(NULL);
}
Cudd_Ref(w);
Cudd_RecursiveDeref(dd,cube);
cube = w;
}
res = Cudd_addExistAbstract(dd,tmp,cube);
if (res == NULL) {
Cudd_RecursiveDeref(dd,tmp);
Cudd_RecursiveDeref(dd,cube);
return(NULL);
}
Cudd_Ref(res);
Cudd_RecursiveDeref(dd,cube);
Cudd_RecursiveDeref(dd,tmp);
Cudd_Deref(res);
return(res);
} /* end of Cudd_addTimesPlus */
/**Function********************************************************************
Synopsis [Performs the triangulation step for the shortest path
computation.]
Description [Implements the semiring multiplication algorithm used in
the triangulation step for the shortest path computation. f
is assumed to depend on variables x (rows) and z (columns). g is
assumed to depend on variables z (rows) and y (columns). The product
of f and g then depends on x (rows) and y (columns). Only the z
variables have to be explicitly identified; they are the
"abstraction" variables. Returns a pointer to the result if
successful; NULL otherwise. ]
SideEffects [None]
SeeAlso [Cudd_addMatrixMultiply Cudd_bddAndAbstract]
******************************************************************************/
DdNode *
Cudd_addTriangle(
DdManager * dd,
DdNode * f,
DdNode * g,
DdNode ** z,
int nz)
{
int i, nvars, *vars;
DdNode *res, *cube;
nvars = dd->size;
vars = ALLOC(int, nvars);
if (vars == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(NULL);
}
for (i = 0; i < nvars; i++) vars[i] = -1;
for (i = 0; i < nz; i++) vars[z[i]->index] = i;
cube = Cudd_addComputeCube(dd, z, NULL, nz);
if (cube == NULL) {
FREE(vars);
return(NULL);
}
cuddRef(cube);
do {
dd->reordered = 0;
res = addTriangleRecur(dd, f, g, vars, cube);
} while (dd->reordered == 1);
if (res != NULL) cuddRef(res);
Cudd_RecursiveDeref(dd,cube);
if (res != NULL) cuddDeref(res);
FREE(vars);
return(res);
} /* end of Cudd_addTriangle */
/**Function********************************************************************
Synopsis [Takes the minimum of a matrix and the outer sum of two vectors.]
Description [Takes the pointwise minimum of a matrix and the outer
sum of two vectors. This procedure is used in the Floyd-Warshall
all-pair shortest path algorithm. Returns a pointer to the result if
successful; NULL otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
DdNode *
Cudd_addOuterSum(
DdManager *dd,
DdNode *M,
DdNode *r,
DdNode *c)
{
DdNode *res;
do {
dd->reordered = 0;
res = cuddAddOuterSumRecur(dd, M, r, c);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_addOuterSum */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_addMatrixMultiply.]
Description [Performs the recursive step of Cudd_addMatrixMultiply.
Returns a pointer to the result if successful; NULL otherwise.]
SideEffects [None]
******************************************************************************/
static DdNode *
addMMRecur(
DdManager * dd,
DdNode * A,
DdNode * B,
int topP,
int * vars)
{
DdNode *zero,
*At, /* positive cofactor of first operand */
*Ae, /* negative cofactor of first operand */
*Bt, /* positive cofactor of second operand */
*Be, /* negative cofactor of second operand */
*t, /* positive cofactor of result */
*e, /* negative cofactor of result */
*scaled, /* scaled result */
*add_scale, /* ADD representing the scaling factor */
*res;
int i; /* loop index */
double scale; /* scaling factor */
int index; /* index of the top variable */
CUDD_VALUE_TYPE value;
unsigned int topA, topB, topV;
DD_CTFP cacheOp;
statLine(dd);
zero = DD_ZERO(dd);
if (A == zero || B == zero) {
return(zero);
}
if (cuddIsConstant(A) && cuddIsConstant(B)) {
/* Compute the scaling factor. It is 2^k, where k is the
** number of summation variables below the current variable.
** Indeed, these constants represent blocks of 2^k identical
** constant values in both A and B.
*/
value = cuddV(A) * cuddV(B);
for (i = 0; i < dd->size; i++) {
if (vars[i]) {
if (dd->perm[i] > topP) {
value *= (CUDD_VALUE_TYPE) 2;
}
}
}
res = cuddUniqueConst(dd, value);
return(res);
}
/* Standardize to increase cache efficiency. Clearly, A*B != B*A
** in matrix multiplication. However, which matrix is which is
** determined by the variables appearing in the ADDs and not by
** which one is passed as first argument.
*/
if (A > B) {
DdNode *tmp = A;
A = B;
B = tmp;
}
topA = cuddI(dd,A->index); topB = cuddI(dd,B->index);
topV = ddMin(topA,topB);
cacheOp = (DD_CTFP) addMMRecur;
res = cuddCacheLookup2(dd,cacheOp,A,B);
if (res != NULL) {
/* If the result is 0, there is no need to normalize.
** Otherwise we count the number of z variables between
** the current depth and the top of the ADDs. These are
** the missing variables that determine the size of the
** constant blocks.
*/
if (res == zero) return(res);
scale = 1.0;
for (i = 0; i < dd->size; i++) {
if (vars[i]) {
if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) {
scale *= 2;
}
}
}
if (scale > 1.0) {
cuddRef(res);
add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale);
if (add_scale == NULL) {
Cudd_RecursiveDeref(dd, res);
return(NULL);
}
cuddRef(add_scale);
scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale);
if (scaled == NULL) {
Cudd_RecursiveDeref(dd, add_scale);
Cudd_RecursiveDeref(dd, res);
return(NULL);
}
cuddRef(scaled);
Cudd_RecursiveDeref(dd, add_scale);
Cudd_RecursiveDeref(dd, res);
res = scaled;
cuddDeref(res);
}
return(res);
}
/* compute the cofactors */
if (topV == topA) {
At = cuddT(A);
Ae = cuddE(A);
} else {
At = Ae = A;
}
if (topV == topB) {
Bt = cuddT(B);
Be = cuddE(B);
} else {
Bt = Be = B;
}
t = addMMRecur(dd, At, Bt, (int)topV, vars);
if (t == NULL) return(NULL);
cuddRef(t);
e = addMMRecur(dd, Ae, Be, (int)topV, vars);
if (e == NULL) {
Cudd_RecursiveDeref(dd, t);
return(NULL);
}
cuddRef(e);
index = dd->invperm[topV];
if (vars[index] == 0) {
/* We have split on either the rows of A or the columns
** of B. We just need to connect the two subresults,
** which correspond to two submatrices of the result.
*/
res = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
if (res == NULL) {
Cudd_RecursiveDeref(dd, t);
Cudd_RecursiveDeref(dd, e);
return(NULL);
}
cuddRef(res);
cuddDeref(t);
cuddDeref(e);
} else {
/* we have simultaneously split on the columns of A and
** the rows of B. The two subresults must be added.
*/
res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e);
if (res == NULL) {
Cudd_RecursiveDeref(dd, t);
Cudd_RecursiveDeref(dd, e);
return(NULL);
}
cuddRef(res);
Cudd_RecursiveDeref(dd, t);
Cudd_RecursiveDeref(dd, e);
}
cuddCacheInsert2(dd,cacheOp,A,B,res);
/* We have computed (and stored in the computed table) a minimal
** result; that is, a result that assumes no summation variables
** between the current depth of the recursion and its top
** variable. We now take into account the z variables by properly
** scaling the result.
*/
if (res != zero) {
scale = 1.0;
for (i = 0; i < dd->size; i++) {
if (vars[i]) {
if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) {
scale *= 2;
}
}
}
if (scale > 1.0) {
add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale);
if (add_scale == NULL) {
Cudd_RecursiveDeref(dd, res);
return(NULL);
}
cuddRef(add_scale);
scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale);
if (scaled == NULL) {
Cudd_RecursiveDeref(dd, res);
Cudd_RecursiveDeref(dd, add_scale);
return(NULL);
}
cuddRef(scaled);
Cudd_RecursiveDeref(dd, add_scale);
Cudd_RecursiveDeref(dd, res);
res = scaled;
}
}
cuddDeref(res);
return(res);
} /* end of addMMRecur */
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_addTriangle.]
Description [Performs the recursive step of Cudd_addTriangle. Returns
a pointer to the result if successful; NULL otherwise.]
SideEffects [None]
******************************************************************************/
static DdNode *
addTriangleRecur(
DdManager * dd,
DdNode * f,
DdNode * g,
int * vars,
DdNode *cube)
{
DdNode *fv, *fvn, *gv, *gvn, *t, *e, *res;
CUDD_VALUE_TYPE value;
int top, topf, topg, index;
statLine(dd);
if (f == DD_PLUS_INFINITY(dd) || g == DD_PLUS_INFINITY(dd)) {
return(DD_PLUS_INFINITY(dd));
}
if (cuddIsConstant(f) && cuddIsConstant(g)) {
value = cuddV(f) + cuddV(g);
res = cuddUniqueConst(dd, value);
return(res);
}
if (f < g) {
DdNode *tmp = f;
f = g;
g = tmp;
}
if (f->ref != 1 || g->ref != 1) {
res = cuddCacheLookup(dd, DD_ADD_TRIANGLE_TAG, f, g, cube);
if (res != NULL) {
return(res);
}
}
topf = cuddI(dd,f->index); topg = cuddI(dd,g->index);
top = ddMin(topf,topg);
if (top == topf) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;}
if (top == topg) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;}
t = addTriangleRecur(dd, fv, gv, vars, cube);
if (t == NULL) return(NULL);
cuddRef(t);
e = addTriangleRecur(dd, fvn, gvn, vars, cube);
if (e == NULL) {
Cudd_RecursiveDeref(dd, t);
return(NULL);
}
cuddRef(e);
index = dd->invperm[top];
if (vars[index] < 0) {
res = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
if (res == NULL) {
Cudd_RecursiveDeref(dd, t);
Cudd_RecursiveDeref(dd, e);
return(NULL);
}
cuddDeref(t);
cuddDeref(e);
} else {
res = cuddAddApplyRecur(dd,Cudd_addMinimum,t,e);
if (res == NULL) {
Cudd_RecursiveDeref(dd, t);
Cudd_RecursiveDeref(dd, e);
return(NULL);
}
cuddRef(res);
Cudd_RecursiveDeref(dd, t);
Cudd_RecursiveDeref(dd, e);
cuddDeref(res);
}
if (f->ref != 1 || g->ref != 1) {
cuddCacheInsert(dd, DD_ADD_TRIANGLE_TAG, f, g, cube, res);
}
return(res);
} /* end of addTriangleRecur */
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_addOuterSum.]
Description [Performs the recursive step of Cudd_addOuterSum.
Returns a pointer to the result if successful; NULL otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static DdNode *
cuddAddOuterSumRecur(
DdManager *dd,
DdNode *M,
DdNode *r,
DdNode *c)
{
DdNode *P, *R, *Mt, *Me, *rt, *re, *ct, *ce, *Rt, *Re;
int topM, topc, topr;
int v, index;
statLine(dd);
/* Check special cases. */
if (r == DD_PLUS_INFINITY(dd) || c == DD_PLUS_INFINITY(dd)) return(M);
if (cuddIsConstant(c) && cuddIsConstant(r)) {
R = cuddUniqueConst(dd,Cudd_V(c)+Cudd_V(r));
cuddRef(R);
if (cuddIsConstant(M)) {
if (cuddV(R) <= cuddV(M)) {
cuddDeref(R);
return(R);
} else {
Cudd_RecursiveDeref(dd,R);
return(M);
}
} else {
P = Cudd_addApply(dd,Cudd_addMinimum,R,M);
cuddRef(P);
Cudd_RecursiveDeref(dd,R);
cuddDeref(P);
return(P);
}
}
/* Check the cache. */
R = cuddCacheLookup(dd,DD_ADD_OUT_SUM_TAG,M,r,c);
if (R != NULL) return(R);
topM = cuddI(dd,M->index); topr = cuddI(dd,r->index);
topc = cuddI(dd,c->index);
v = ddMin(topM,ddMin(topr,topc));
/* Compute cofactors. */
if (topM == v) { Mt = cuddT(M); Me = cuddE(M); } else { Mt = Me = M; }
if (topr == v) { rt = cuddT(r); re = cuddE(r); } else { rt = re = r; }
if (topc == v) { ct = cuddT(c); ce = cuddE(c); } else { ct = ce = c; }
/* Recursively solve. */
Rt = cuddAddOuterSumRecur(dd,Mt,rt,ct);
if (Rt == NULL) return(NULL);
cuddRef(Rt);
Re = cuddAddOuterSumRecur(dd,Me,re,ce);
if (Re == NULL) {
Cudd_RecursiveDeref(dd, Rt);
return(NULL);
}
cuddRef(Re);
index = dd->invperm[v];
R = (Rt == Re) ? Rt : cuddUniqueInter(dd,index,Rt,Re);
if (R == NULL) {
Cudd_RecursiveDeref(dd, Rt);
Cudd_RecursiveDeref(dd, Re);
return(NULL);
}
cuddDeref(Rt);
cuddDeref(Re);
/* Store the result in the cache. */
cuddCacheInsert(dd,DD_ADD_OUT_SUM_TAG,M,r,c,R);
return(R);
} /* end of cuddAddOuterSumRecur */

File diff suppressed because it is too large Load Diff

517
cudd_local/cudd/cuddRead.c Normal file
View File

@@ -0,0 +1,517 @@
/**CFile***********************************************************************
FileName [cuddRead.c]
PackageName [cudd]
Synopsis [Functions to read in a matrix]
Description [External procedures included in this module:
<ul>
<li> Cudd_addRead()
<li> Cudd_bddRead()
</ul>]
SeeAlso [cudd_addHarwell.c]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddRead.c,v 1.7 2012/02/05 01:07:19 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Reads in a sparse matrix.]
Description [Reads in a sparse matrix specified in a simple format.
The first line of the input contains the numbers of rows and columns.
The remaining lines contain the elements of the matrix, one per line.
Given a background value
(specified by the background field of the manager), only the values
different from it are explicitly listed. Each foreground element is
described by two integers, i.e., the row and column number, and a
real number, i.e., the value.<p>
Cudd_addRead produces an ADD that depends on two sets of variables: x
and y. The x variables (x\[0\] ... x\[nx-1\]) encode the row index and
the y variables (y\[0\] ... y\[ny-1\]) encode the column index.
x\[0\] and y\[0\] are the most significant bits in the indices.
The variables may already exist or may be created by the function.
The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.<p>
On input, nx and ny hold the numbers
of row and column variables already in existence. On output, they
hold the numbers of row and column variables actually used by the
matrix. When Cudd_addRead creates the variable arrays,
the index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.
When some variables already exist Cudd_addRead expects the indices
of the existing x variables to be bx+i*sx, and the indices of the
existing y variables to be by+i*sy.<p>
m and n are set to the numbers of rows and columns of the
matrix. Their values on input are immaterial.
The ADD for the
sparse matrix is returned in E, and its reference count is > 0.
Cudd_addRead returns 1 in case of success; 0 otherwise.]
SideEffects [nx and ny are set to the numbers of row and column
variables. m and n are set to the numbers of rows and columns. x and y
are possibly extended to represent the array of row and column
variables. Similarly for xn and yn_, which hold on return from
Cudd_addRead the complements of the row and column variables.]
SeeAlso [Cudd_addHarwell Cudd_bddRead]
******************************************************************************/
int
Cudd_addRead(
FILE * fp /* input file pointer */,
DdManager * dd /* DD manager */,
DdNode ** E /* characteristic function of the graph */,
DdNode *** x /* array of row variables */,
DdNode *** y /* array of column variables */,
DdNode *** xn /* array of complemented row variables */,
DdNode *** yn_ /* array of complemented column variables */,
int * nx /* number or row variables */,
int * ny /* number or column variables */,
int * m /* number of rows */,
int * n /* number of columns */,
int bx /* first index of row variables */,
int sx /* step of row variables */,
int by /* first index of column variables */,
int sy /* step of column variables */)
{
DdNode *one, *zero;
DdNode *w, *neW;
DdNode *minterm1;
int u, v, err, i, nv;
int lnx, lny;
CUDD_VALUE_TYPE val;
DdNode **lx, **ly, **lxn, **lyn;
one = DD_ONE(dd);
zero = DD_ZERO(dd);
err = fscanf(fp, "%d %d", &u, &v);
if (err == EOF) {
return(0);
} else if (err != 2) {
return(0);
}
*m = u;
/* Compute the number of x variables. */
lx = *x; lxn = *xn;
u--; /* row and column numbers start from 0 */
for (lnx=0; u > 0; lnx++) {
u >>= 1;
}
/* Here we rely on the fact that REALLOC of a null pointer is
** translates to an ALLOC.
*/
if (lnx > *nx) {
*x = lx = REALLOC(DdNode *, *x, lnx);
if (lx == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
*xn = lxn = REALLOC(DdNode *, *xn, lnx);
if (lxn == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
}
*n = v;
/* Compute the number of y variables. */
ly = *y; lyn = *yn_;
v--; /* row and column numbers start from 0 */
for (lny=0; v > 0; lny++) {
v >>= 1;
}
/* Here we rely on the fact that REALLOC of a null pointer is
** translates to an ALLOC.
*/
if (lny > *ny) {
*y = ly = REALLOC(DdNode *, *y, lny);
if (ly == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
*yn_ = lyn = REALLOC(DdNode *, *yn_, lny);
if (lyn == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
}
/* Create all new variables. */
for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) {
do {
dd->reordered = 0;
lx[i] = cuddUniqueInter(dd, nv, one, zero);
} while (dd->reordered == 1);
if (lx[i] == NULL) return(0);
cuddRef(lx[i]);
do {
dd->reordered = 0;
lxn[i] = cuddUniqueInter(dd, nv, zero, one);
} while (dd->reordered == 1);
if (lxn[i] == NULL) return(0);
cuddRef(lxn[i]);
}
for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) {
do {
dd->reordered = 0;
ly[i] = cuddUniqueInter(dd, nv, one, zero);
} while (dd->reordered == 1);
if (ly[i] == NULL) return(0);
cuddRef(ly[i]);
do {
dd->reordered = 0;
lyn[i] = cuddUniqueInter(dd, nv, zero, one);
} while (dd->reordered == 1);
if (lyn[i] == NULL) return(0);
cuddRef(lyn[i]);
}
*nx = lnx;
*ny = lny;
*E = dd->background; /* this call will never cause reordering */
cuddRef(*E);
while (! feof(fp)) {
err = fscanf(fp, "%d %d %lf", &u, &v, &val);
if (err == EOF) {
break;
} else if (err != 3) {
return(0);
} else if (u >= *m || v >= *n || u < 0 || v < 0) {
return(0);
}
minterm1 = one; cuddRef(minterm1);
/* Build minterm1 corresponding to this arc */
for (i = lnx - 1; i>=0; i--) {
if (u & 1) {
w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lx[i]);
} else {
w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lxn[i]);
}
if (w == NULL) {
Cudd_RecursiveDeref(dd, minterm1);
return(0);
}
cuddRef(w);
Cudd_RecursiveDeref(dd, minterm1);
minterm1 = w;
u >>= 1;
}
for (i = lny - 1; i>=0; i--) {
if (v & 1) {
w = Cudd_addApply(dd, Cudd_addTimes, minterm1, ly[i]);
} else {
w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lyn[i]);
}
if (w == NULL) {
Cudd_RecursiveDeref(dd, minterm1);
return(0);
}
cuddRef(w);
Cudd_RecursiveDeref(dd, minterm1);
minterm1 = w;
v >>= 1;
}
/* Create new constant node if necessary.
** This call will never cause reordering.
*/
neW = cuddUniqueConst(dd, val);
if (neW == NULL) {
Cudd_RecursiveDeref(dd, minterm1);
return(0);
}
cuddRef(neW);
w = Cudd_addIte(dd, minterm1, neW, *E);
if (w == NULL) {
Cudd_RecursiveDeref(dd, minterm1);
Cudd_RecursiveDeref(dd, neW);
return(0);
}
cuddRef(w);
Cudd_RecursiveDeref(dd, minterm1);
Cudd_RecursiveDeref(dd, neW);
Cudd_RecursiveDeref(dd, *E);
*E = w;
}
return(1);
} /* end of Cudd_addRead */
/**Function********************************************************************
Synopsis [Reads in a graph (without labels) given as a list of arcs.]
Description [Reads in a graph (without labels) given as an adjacency
matrix. The first line of the input contains the numbers of rows and
columns of the adjacency matrix. The remaining lines contain the arcs
of the graph, one per line. Each arc is described by two integers,
i.e., the row and column number, or the indices of the two endpoints.
Cudd_bddRead produces a BDD that depends on two sets of variables: x
and y. The x variables (x\[0\] ... x\[nx-1\]) encode
the row index and the y variables (y\[0\] ... y\[ny-1\]) encode the
column index. x\[0\] and y\[0\] are the most significant bits in the
indices.
The variables may already exist or may be created by the function.
The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.<p>
On input, nx and ny hold the numbers of row and column variables already
in existence. On output, they hold the numbers of row and column
variables actually used by the matrix. When Cudd_bddRead creates the
variable arrays, the index of x\[i\] is bx+i*sx, and the index of
y\[i\] is by+i*sy. When some variables already exist, Cudd_bddRead
expects the indices of the existing x variables to be bx+i*sx, and the
indices of the existing y variables to be by+i*sy.<p>
m and n are set to the numbers of rows and columns of the
matrix. Their values on input are immaterial. The BDD for the graph
is returned in E, and its reference count is > 0. Cudd_bddRead returns
1 in case of success; 0 otherwise.]
SideEffects [nx and ny are set to the numbers of row and column
variables. m and n are set to the numbers of rows and columns. x and y
are possibly extended to represent the array of row and column
variables.]
SeeAlso [Cudd_addHarwell Cudd_addRead]
******************************************************************************/
int
Cudd_bddRead(
FILE * fp /* input file pointer */,
DdManager * dd /* DD manager */,
DdNode ** E /* characteristic function of the graph */,
DdNode *** x /* array of row variables */,
DdNode *** y /* array of column variables */,
int * nx /* number or row variables */,
int * ny /* number or column variables */,
int * m /* number of rows */,
int * n /* number of columns */,
int bx /* first index of row variables */,
int sx /* step of row variables */,
int by /* first index of column variables */,
int sy /* step of column variables */)
{
DdNode *one, *zero;
DdNode *w;
DdNode *minterm1;
int u, v, err, i, nv;
int lnx, lny;
DdNode **lx, **ly;
one = DD_ONE(dd);
zero = Cudd_Not(one);
err = fscanf(fp, "%d %d", &u, &v);
if (err == EOF) {
return(0);
} else if (err != 2) {
return(0);
}
*m = u;
/* Compute the number of x variables. */
lx = *x;
u--; /* row and column numbers start from 0 */
for (lnx=0; u > 0; lnx++) {
u >>= 1;
}
if (lnx > *nx) {
*x = lx = REALLOC(DdNode *, *x, lnx);
if (lx == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
}
*n = v;
/* Compute the number of y variables. */
ly = *y;
v--; /* row and column numbers start from 0 */
for (lny=0; v > 0; lny++) {
v >>= 1;
}
if (lny > *ny) {
*y = ly = REALLOC(DdNode *, *y, lny);
if (ly == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(0);
}
}
/* Create all new variables. */
for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) {
do {
dd->reordered = 0;
lx[i] = cuddUniqueInter(dd, nv, one, zero);
} while (dd->reordered == 1);
if (lx[i] == NULL) return(0);
cuddRef(lx[i]);
}
for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) {
do {
dd->reordered = 0;
ly[i] = cuddUniqueInter(dd, nv, one, zero);
} while (dd->reordered == 1);
if (ly[i] == NULL) return(0);
cuddRef(ly[i]);
}
*nx = lnx;
*ny = lny;
*E = zero; /* this call will never cause reordering */
cuddRef(*E);
while (! feof(fp)) {
err = fscanf(fp, "%d %d", &u, &v);
if (err == EOF) {
break;
} else if (err != 2) {
return(0);
} else if (u >= *m || v >= *n || u < 0 || v < 0) {
return(0);
}
minterm1 = one; cuddRef(minterm1);
/* Build minterm1 corresponding to this arc. */
for (i = lnx - 1; i>=0; i--) {
if (u & 1) {
w = Cudd_bddAnd(dd, minterm1, lx[i]);
} else {
w = Cudd_bddAnd(dd, minterm1, Cudd_Not(lx[i]));
}
if (w == NULL) {
Cudd_RecursiveDeref(dd, minterm1);
return(0);
}
cuddRef(w);
Cudd_RecursiveDeref(dd,minterm1);
minterm1 = w;
u >>= 1;
}
for (i = lny - 1; i>=0; i--) {
if (v & 1) {
w = Cudd_bddAnd(dd, minterm1, ly[i]);
} else {
w = Cudd_bddAnd(dd, minterm1, Cudd_Not(ly[i]));
}
if (w == NULL) {
Cudd_RecursiveDeref(dd, minterm1);
return(0);
}
cuddRef(w);
Cudd_RecursiveDeref(dd, minterm1);
minterm1 = w;
v >>= 1;
}
w = Cudd_bddAnd(dd, Cudd_Not(minterm1), Cudd_Not(*E));
if (w == NULL) {
Cudd_RecursiveDeref(dd, minterm1);
return(0);
}
w = Cudd_Not(w);
cuddRef(w);
Cudd_RecursiveDeref(dd, minterm1);
Cudd_RecursiveDeref(dd, *E);
*E = w;
}
return(1);
} /* end of Cudd_bddRead */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/

808
cudd_local/cudd/cuddRef.c Normal file
View File

@@ -0,0 +1,808 @@
/**CFile***********************************************************************
FileName [cuddRef.c]
PackageName [cudd]
Synopsis [Functions that manipulate the reference counts.]
Description [External procedures included in this module:
<ul>
<li> Cudd_Ref()
<li> Cudd_RecursiveDeref()
<li> Cudd_IterDerefBdd()
<li> Cudd_DelayedDerefBdd()
<li> Cudd_RecursiveDerefZdd()
<li> Cudd_Deref()
<li> Cudd_CheckZeroRef()
</ul>
Internal procedures included in this module:
<ul>
<li> cuddReclaim()
<li> cuddReclaimZdd()
<li> cuddClearDeathRow()
<li> cuddShrinkDeathRow()
<li> cuddIsInDeathRow()
<li> cuddTimesInDeathRow()
</ul>
]
SeeAlso []
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddRef.c,v 1.29 2012/02/05 01:07:19 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Increases the reference count of a node, if it is not
saturated.]
Description []
SideEffects [None]
SeeAlso [Cudd_RecursiveDeref Cudd_Deref]
******************************************************************************/
void
Cudd_Ref(
DdNode * n)
{
n = Cudd_Regular(n);
cuddSatInc(n->ref);
} /* end of Cudd_Ref */
/**Function********************************************************************
Synopsis [Decreases the reference count of node n.]
Description [Decreases the reference count of node n. If n dies,
recursively decreases the reference counts of its children. It is
used to dispose of a DD that is no longer needed.]
SideEffects [None]
SeeAlso [Cudd_Deref Cudd_Ref Cudd_RecursiveDerefZdd]
******************************************************************************/
void
Cudd_RecursiveDeref(
DdManager * table,
DdNode * n)
{
DdNode *N;
int ord;
DdNodePtr *stack = table->stack;
int SP = 1;
unsigned int live = table->keys - table->dead;
if (live > table->peakLiveNodes) {
table->peakLiveNodes = live;
}
N = Cudd_Regular(n);
do {
#ifdef DD_DEBUG
assert(N->ref != 0);
#endif
if (N->ref == 1) {
N->ref = 0;
table->dead++;
#ifdef DD_STATS
table->nodesDropped++;
#endif
if (cuddIsConstant(N)) {
table->constants.dead++;
N = stack[--SP];
} else {
ord = table->perm[N->index];
stack[SP++] = Cudd_Regular(cuddE(N));
table->subtables[ord].dead++;
N = cuddT(N);
}
} else {
cuddSatDec(N->ref);
N = stack[--SP];
}
} while (SP != 0);
} /* end of Cudd_RecursiveDeref */
/**Function********************************************************************
Synopsis [Decreases the reference count of BDD node n.]
Description [Decreases the reference count of node n. If n dies,
recursively decreases the reference counts of its children. It is
used to dispose of a BDD that is no longer needed. It is more
efficient than Cudd_RecursiveDeref, but it cannot be used on
ADDs. The greater efficiency comes from being able to assume that no
constant node will ever die as a result of a call to this
procedure.]
SideEffects [None]
SeeAlso [Cudd_RecursiveDeref Cudd_DelayedDerefBdd]
******************************************************************************/
void
Cudd_IterDerefBdd(
DdManager * table,
DdNode * n)
{
DdNode *N;
int ord;
DdNodePtr *stack = table->stack;
int SP = 1;
unsigned int live = table->keys - table->dead;
if (live > table->peakLiveNodes) {
table->peakLiveNodes = live;
}
N = Cudd_Regular(n);
do {
#ifdef DD_DEBUG
assert(N->ref != 0);
#endif
if (N->ref == 1) {
N->ref = 0;
table->dead++;
#ifdef DD_STATS
table->nodesDropped++;
#endif
ord = table->perm[N->index];
stack[SP++] = Cudd_Regular(cuddE(N));
table->subtables[ord].dead++;
N = cuddT(N);
} else {
cuddSatDec(N->ref);
N = stack[--SP];
}
} while (SP != 0);
} /* end of Cudd_IterDerefBdd */
/**Function********************************************************************
Synopsis [Decreases the reference count of BDD node n.]
Description [Enqueues node n for later dereferencing. If the queue
is full decreases the reference count of the oldest node N to make
room for n. If N dies, recursively decreases the reference counts of
its children. It is used to dispose of a BDD that is currently not
needed, but may be useful again in the near future. The dereferencing
proper is done as in Cudd_IterDerefBdd.]
SideEffects [None]
SeeAlso [Cudd_RecursiveDeref Cudd_IterDerefBdd]
******************************************************************************/
void
Cudd_DelayedDerefBdd(
DdManager * table,
DdNode * n)
{
DdNode *N;
int ord;
DdNodePtr *stack;
int SP;
unsigned int live = table->keys - table->dead;
if (live > table->peakLiveNodes) {
table->peakLiveNodes = live;
}
n = Cudd_Regular(n);
#ifdef DD_DEBUG
assert(n->ref != 0);
#endif
#ifdef DD_NO_DEATH_ROW
N = n;
#else
if (cuddIsConstant(n) || n->ref > 1) {
#ifdef DD_DEBUG
assert(n->ref != 1 && (!cuddIsConstant(n) || n == DD_ONE(table)));
#endif
cuddSatDec(n->ref);
return;
}
N = table->deathRow[table->nextDead];
if (N != NULL) {
#endif
#ifdef DD_DEBUG
assert(!Cudd_IsComplement(N));
#endif
stack = table->stack;
SP = 1;
do {
#ifdef DD_DEBUG
assert(N->ref != 0);
#endif
if (N->ref == 1) {
N->ref = 0;
table->dead++;
#ifdef DD_STATS
table->nodesDropped++;
#endif
ord = table->perm[N->index];
stack[SP++] = Cudd_Regular(cuddE(N));
table->subtables[ord].dead++;
N = cuddT(N);
} else {
cuddSatDec(N->ref);
N = stack[--SP];
}
} while (SP != 0);
#ifndef DD_NO_DEATH_ROW
}
table->deathRow[table->nextDead] = n;
/* Udate insertion point. */
table->nextDead++;
table->nextDead &= table->deadMask;
#if 0
if (table->nextDead == table->deathRowDepth) {
if (table->deathRowDepth < table->looseUpTo / 2) {
extern void (*MMoutOfMemory)(long);
void (*saveHandler)(long) = MMoutOfMemory;
DdNodePtr *newRow;
MMoutOfMemory = Cudd_OutOfMem;
newRow = REALLOC(DdNodePtr,table->deathRow,2*table->deathRowDepth);
MMoutOfMemory = saveHandler;
if (newRow == NULL) {
table->nextDead = 0;
} else {
int i;
table->memused += table->deathRowDepth;
i = table->deathRowDepth;
table->deathRowDepth <<= 1;
for (; i < table->deathRowDepth; i++) {
newRow[i] = NULL;
}
table->deadMask = table->deathRowDepth - 1;
table->deathRow = newRow;
}
} else {
table->nextDead = 0;
}
}
#endif
#endif
} /* end of Cudd_DelayedDerefBdd */
/**Function********************************************************************
Synopsis [Decreases the reference count of ZDD node n.]
Description [Decreases the reference count of ZDD node n. If n dies,
recursively decreases the reference counts of its children. It is
used to dispose of a ZDD that is no longer needed.]
SideEffects [None]
SeeAlso [Cudd_Deref Cudd_Ref Cudd_RecursiveDeref]
******************************************************************************/
void
Cudd_RecursiveDerefZdd(
DdManager * table,
DdNode * n)
{
DdNode *N;
int ord;
DdNodePtr *stack = table->stack;
int SP = 1;
N = n;
do {
#ifdef DD_DEBUG
assert(N->ref != 0);
#endif
cuddSatDec(N->ref);
if (N->ref == 0) {
table->deadZ++;
#ifdef DD_STATS
table->nodesDropped++;
#endif
#ifdef DD_DEBUG
assert(!cuddIsConstant(N));
#endif
ord = table->permZ[N->index];
stack[SP++] = cuddE(N);
table->subtableZ[ord].dead++;
N = cuddT(N);
} else {
N = stack[--SP];
}
} while (SP != 0);
} /* end of Cudd_RecursiveDerefZdd */
/**Function********************************************************************
Synopsis [Decreases the reference count of node.]
Description [Decreases the reference count of node. It is primarily
used in recursive procedures to decrease the ref count of a result
node before returning it. This accomplishes the goal of removing the
protection applied by a previous Cudd_Ref.]
SideEffects [None]
SeeAlso [Cudd_RecursiveDeref Cudd_RecursiveDerefZdd Cudd_Ref]
******************************************************************************/
void
Cudd_Deref(
DdNode * node)
{
node = Cudd_Regular(node);
cuddSatDec(node->ref);
} /* end of Cudd_Deref */
/**Function********************************************************************
Synopsis [Checks the unique table for nodes with non-zero reference
counts.]
Description [Checks the unique table for nodes with non-zero
reference counts. It is normally called before Cudd_Quit to make sure
that there are no memory leaks due to missing Cudd_RecursiveDeref's.
Takes into account that reference counts may saturate and that the
basic constants and the projection functions are referenced by the
manager. Returns the number of nodes with non-zero reference count.
(Except for the cases mentioned above.)]
SideEffects [None]
SeeAlso []
******************************************************************************/
int
Cudd_CheckZeroRef(
DdManager * manager)
{
int size;
int i, j;
int remain; /* the expected number of remaining references to one */
DdNodePtr *nodelist;
DdNode *node;
DdNode *sentinel = &(manager->sentinel);
DdSubtable *subtable;
int count = 0;
int index;
#ifndef DD_NO_DEATH_ROW
cuddClearDeathRow(manager);
#endif
/* First look at the BDD/ADD subtables. */
remain = 1; /* reference from the manager */
size = manager->size;
remain += 2 * size; /* reference from the BDD projection functions */
for (i = 0; i < size; i++) {
subtable = &(manager->subtables[i]);
nodelist = subtable->nodelist;
for (j = 0; (unsigned) j < subtable->slots; j++) {
node = nodelist[j];
while (node != sentinel) {
if (node->ref != 0 && node->ref != DD_MAXREF) {
index = (int) node->index;
if (node != manager->vars[index]) {
count++;
} else {
if (node->ref != 1) {
count++;
}
}
}
node = node->next;
}
}
}
/* Then look at the ZDD subtables. */
size = manager->sizeZ;
if (size) /* references from ZDD universe */
remain += 2;
for (i = 0; i < size; i++) {
subtable = &(manager->subtableZ[i]);
nodelist = subtable->nodelist;
for (j = 0; (unsigned) j < subtable->slots; j++) {
node = nodelist[j];
while (node != NULL) {
if (node->ref != 0 && node->ref != DD_MAXREF) {
index = (int) node->index;
if (node == manager->univ[manager->permZ[index]]) {
if (node->ref > 2) {
count++;
}
} else {
count++;
}
}
node = node->next;
}
}
}
/* Now examine the constant table. Plusinfinity, minusinfinity, and
** zero are referenced by the manager. One is referenced by the
** manager, by the ZDD universe, and by all projection functions.
** All other nodes should have no references.
*/
nodelist = manager->constants.nodelist;
for (j = 0; (unsigned) j < manager->constants.slots; j++) {
node = nodelist[j];
while (node != NULL) {
if (node->ref != 0 && node->ref != DD_MAXREF) {
if (node == manager->one) {
if ((int) node->ref != remain) {
count++;
}
} else if (node == manager->zero ||
node == manager->plusinfinity ||
node == manager->minusinfinity) {
if (node->ref != 1) {
count++;
}
} else {
count++;
}
}
node = node->next;
}
}
return(count);
} /* end of Cudd_CheckZeroRef */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Brings children of a dead node back.]
Description []
SideEffects [None]
SeeAlso [cuddReclaimZdd]
******************************************************************************/
void
cuddReclaim(
DdManager * table,
DdNode * n)
{
DdNode *N;
int ord;
DdNodePtr *stack = table->stack;
int SP = 1;
double initialDead = table->dead;
N = Cudd_Regular(n);
#ifdef DD_DEBUG
assert(N->ref == 0);
#endif
do {
if (N->ref == 0) {
N->ref = 1;
table->dead--;
if (cuddIsConstant(N)) {
table->constants.dead--;
N = stack[--SP];
} else {
ord = table->perm[N->index];
stack[SP++] = Cudd_Regular(cuddE(N));
table->subtables[ord].dead--;
N = cuddT(N);
}
} else {
cuddSatInc(N->ref);
N = stack[--SP];
}
} while (SP != 0);
N = Cudd_Regular(n);
cuddSatDec(N->ref);
table->reclaimed += initialDead - table->dead;
} /* end of cuddReclaim */
/**Function********************************************************************
Synopsis [Brings children of a dead ZDD node back.]
Description []
SideEffects [None]
SeeAlso [cuddReclaim]
******************************************************************************/
void
cuddReclaimZdd(
DdManager * table,
DdNode * n)
{
DdNode *N;
int ord;
DdNodePtr *stack = table->stack;
int SP = 1;
N = n;
#ifdef DD_DEBUG
assert(N->ref == 0);
#endif
do {
cuddSatInc(N->ref);
if (N->ref == 1) {
table->deadZ--;
table->reclaimed++;
#ifdef DD_DEBUG
assert(!cuddIsConstant(N));
#endif
ord = table->permZ[N->index];
stack[SP++] = cuddE(N);
table->subtableZ[ord].dead--;
N = cuddT(N);
} else {
N = stack[--SP];
}
} while (SP != 0);
cuddSatDec(n->ref);
} /* end of cuddReclaimZdd */
/**Function********************************************************************
Synopsis [Shrinks the death row.]
Description [Shrinks the death row by a factor of four.]
SideEffects [None]
SeeAlso [cuddClearDeathRow]
******************************************************************************/
void
cuddShrinkDeathRow(
DdManager *table)
{
#ifndef DD_NO_DEATH_ROW
int i;
if (table->deathRowDepth > 3) {
for (i = table->deathRowDepth/4; i < table->deathRowDepth; i++) {
if (table->deathRow[i] == NULL) break;
Cudd_IterDerefBdd(table,table->deathRow[i]);
table->deathRow[i] = NULL;
}
table->deathRowDepth /= 4;
table->deadMask = table->deathRowDepth - 1;
if ((unsigned) table->nextDead > table->deadMask) {
table->nextDead = 0;
}
table->deathRow = REALLOC(DdNodePtr, table->deathRow,
table->deathRowDepth);
}
#endif
} /* end of cuddShrinkDeathRow */
/**Function********************************************************************
Synopsis [Clears the death row.]
Description []
SideEffects [None]
SeeAlso [Cudd_DelayedDerefBdd Cudd_IterDerefBdd Cudd_CheckZeroRef
cuddGarbageCollect]
******************************************************************************/
void
cuddClearDeathRow(
DdManager *table)
{
#ifndef DD_NO_DEATH_ROW
int i;
for (i = 0; i < table->deathRowDepth; i++) {
if (table->deathRow[i] == NULL) break;
Cudd_IterDerefBdd(table,table->deathRow[i]);
table->deathRow[i] = NULL;
}
#ifdef DD_DEBUG
for (; i < table->deathRowDepth; i++) {
assert(table->deathRow[i] == NULL);
}
#endif
table->nextDead = 0;
#endif
} /* end of cuddClearDeathRow */
/**Function********************************************************************
Synopsis [Checks whether a node is in the death row.]
Description [Checks whether a node is in the death row. Returns the
position of the first occurrence if the node is present; -1
otherwise.]
SideEffects [None]
SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow]
******************************************************************************/
int
cuddIsInDeathRow(
DdManager *dd,
DdNode *f)
{
#ifndef DD_NO_DEATH_ROW
int i;
for (i = 0; i < dd->deathRowDepth; i++) {
if (f == dd->deathRow[i]) {
return(i);
}
}
#endif
return(-1);
} /* end of cuddIsInDeathRow */
/**Function********************************************************************
Synopsis [Counts how many times a node is in the death row.]
Description []
SideEffects [None]
SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow cuddIsInDeathRow]
******************************************************************************/
int
cuddTimesInDeathRow(
DdManager *dd,
DdNode *f)
{
int count = 0;
#ifndef DD_NO_DEATH_ROW
int i;
for (i = 0; i < dd->deathRowDepth; i++) {
count += f == dd->deathRow[i];
}
#endif
return(count);
} /* end of cuddTimesInDeathRow */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

1774
cudd_local/cudd/cuddSat.c Normal file

File diff suppressed because it is too large Load Diff

318
cudd_local/cudd/cuddSign.c Normal file
View File

@@ -0,0 +1,318 @@
/**CFile***********************************************************************
FileName [cuddSign.c]
PackageName [cudd]
Synopsis [Computation of signatures.]
Description [External procedures included in this module:
<ul>
<li> Cudd_CofMinterm();
</ul>
Static procedures included in this module:
<ul>
<li> ddCofMintermAux()
</ul>
]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddSign.c,v 1.24 2012/02/05 01:07:19 fabio Exp $";
#endif
static int size;
#ifdef DD_STATS
static int num_calls; /* should equal 2n-1 (n is the # of nodes) */
static int table_mem;
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static double * ddCofMintermAux (DdManager *dd, DdNode *node, st_table *table);
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Computes the fraction of minterms in the on-set of all the
positive cofactors of a BDD or ADD.]
Description [Computes the fraction of minterms in the on-set of all
the positive cofactors of DD. Returns the pointer to an array of
doubles if successful; NULL otherwise. The array has as many
positions as there are BDD variables in the manager plus one. The
last position of the array contains the fraction of the minterms in
the ON-set of the function represented by the BDD or ADD. The other
positions of the array hold the variable signatures.]
SideEffects [None]
******************************************************************************/
double *
Cudd_CofMinterm(
DdManager * dd,
DdNode * node)
{
st_table *table;
double *values;
double *result = NULL;
int i, firstLevel;
#ifdef DD_STATS
unsigned long startTime;
startTime = util_cpu_time();
num_calls = 0;
table_mem = sizeof(st_table);
#endif
table = st_init_table(st_ptrcmp, st_ptrhash);
if (table == NULL) {
(void) fprintf(dd->err,
"out-of-memory, couldn't measure DD cofactors.\n");
dd->errorCode = CUDD_MEMORY_OUT;
return(NULL);
}
size = dd->size;
values = ddCofMintermAux(dd, node, table);
if (values != NULL) {
result = ALLOC(double,size + 1);
if (result != NULL) {
#ifdef DD_STATS
table_mem += (size + 1) * sizeof(double);
#endif
if (Cudd_IsConstant(node))
firstLevel = 1;
else
firstLevel = cuddI(dd,Cudd_Regular(node)->index);
for (i = 0; i < size; i++) {
if (i >= cuddI(dd,Cudd_Regular(node)->index)) {
result[dd->invperm[i]] = values[i - firstLevel];
} else {
result[dd->invperm[i]] = values[size - firstLevel];
}
}
result[size] = values[size - firstLevel];
} else {
dd->errorCode = CUDD_MEMORY_OUT;
}
}
#ifdef DD_STATS
table_mem += table->num_bins * sizeof(st_table_entry *);
#endif
if (Cudd_Regular(node)->ref == 1) FREE(values);
st_foreach(table, cuddStCountfree, NULL);
st_free_table(table);
#ifdef DD_STATS
(void) fprintf(dd->out,"Number of calls: %d\tTable memory: %d bytes\n",
num_calls, table_mem);
(void) fprintf(dd->out,"Time to compute measures: %s\n",
util_print_time(util_cpu_time() - startTime));
#endif
if (result == NULL) {
(void) fprintf(dd->out,
"out-of-memory, couldn't measure DD cofactors.\n");
dd->errorCode = CUDD_MEMORY_OUT;
}
return(result);
} /* end of Cudd_CofMinterm */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Recursive Step for Cudd_CofMinterm function.]
Description [Traverses the DD node and computes the fraction of
minterms in the on-set of all positive cofactors simultaneously.
It allocates an array with two more entries than there are
variables below the one labeling the node. One extra entry (the
first in the array) is for the variable labeling the node. The other
entry (the last one in the array) holds the fraction of minterms of
the function rooted at node. Each other entry holds the value for
one cofactor. The array is put in a symbol table, to avoid repeated
computation, and its address is returned by the procedure, for use
by the caller. Returns a pointer to the array of cofactor measures.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static double *
ddCofMintermAux(
DdManager * dd,
DdNode * node,
st_table * table)
{
DdNode *N; /* regular version of node */
DdNode *Nv, *Nnv;
double *values;
double *valuesT, *valuesE;
int i;
int localSize, localSizeT, localSizeE;
double vT, vE;
statLine(dd);
#ifdef DD_STATS
num_calls++;
#endif
if (st_lookup(table, node, &values)) {
return(values);
}
N = Cudd_Regular(node);
if (cuddIsConstant(N)) {
localSize = 1;
} else {
localSize = size - cuddI(dd,N->index) + 1;
}
values = ALLOC(double, localSize);
if (values == NULL) {
dd->errorCode = CUDD_MEMORY_OUT;
return(NULL);
}
if (cuddIsConstant(N)) {
if (node == DD_ZERO(dd) || node == Cudd_Not(DD_ONE(dd))) {
values[0] = 0.0;
} else {
values[0] = 1.0;
}
} else {
Nv = Cudd_NotCond(cuddT(N),N!=node);
Nnv = Cudd_NotCond(cuddE(N),N!=node);
valuesT = ddCofMintermAux(dd, Nv, table);
if (valuesT == NULL) return(NULL);
valuesE = ddCofMintermAux(dd, Nnv, table);
if (valuesE == NULL) return(NULL);
if (Cudd_IsConstant(Nv)) {
localSizeT = 1;
} else {
localSizeT = size - cuddI(dd,Cudd_Regular(Nv)->index) + 1;
}
if (Cudd_IsConstant(Nnv)) {
localSizeE = 1;
} else {
localSizeE = size - cuddI(dd,Cudd_Regular(Nnv)->index) + 1;
}
values[0] = valuesT[localSizeT - 1];
for (i = 1; i < localSize; i++) {
if (i >= cuddI(dd,Cudd_Regular(Nv)->index) - cuddI(dd,N->index)) {
vT = valuesT[i - cuddI(dd,Cudd_Regular(Nv)->index) +
cuddI(dd,N->index)];
} else {
vT = valuesT[localSizeT - 1];
}
if (i >= cuddI(dd,Cudd_Regular(Nnv)->index) - cuddI(dd,N->index)) {
vE = valuesE[i - cuddI(dd,Cudd_Regular(Nnv)->index) +
cuddI(dd,N->index)];
} else {
vE = valuesE[localSizeE - 1];
}
values[i] = (vT + vE) / 2.0;
}
if (Cudd_Regular(Nv)->ref == 1) FREE(valuesT);
if (Cudd_Regular(Nnv)->ref == 1) FREE(valuesE);
}
if (N->ref > 1) {
if (st_add_direct(table, (char *) node, (char *) values) == ST_OUT_OF_MEM) {
FREE(values);
return(NULL);
}
#ifdef DD_STATS
table_mem += localSize * sizeof(double) + sizeof(st_table_entry);
#endif
}
return(values);
} /* end of ddCofMintermAux */

366
cudd_local/cudd/cuddSolve.c Normal file
View File

@@ -0,0 +1,366 @@
/**CFile***********************************************************************
FileName [cuddSolve.c]
PackageName [cudd]
Synopsis [Boolean equation solver and related functions.]
Description [External functions included in this modoule:
<ul>
<li> Cudd_SolveEqn()
<li> Cudd_VerifySol()
</ul>
Internal functions included in this module:
<ul>
<li> cuddSolveEqnRecur()
<li> cuddVerifySol()
</ul> ]
SeeAlso []
Author [Balakrishna Kumthekar]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Structure declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddSolve.c,v 1.13 2012/02/05 01:07:19 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Implements the solution of F(x,y) = 0.]
Description [Implements the solution for F(x,y) = 0. The return
value is the consistency condition. The y variables are the unknowns
and the remaining variables are the parameters. Returns the
consistency condition if successful; NULL otherwise. Cudd_SolveEqn
allocates an array and fills it with the indices of the
unknowns. This array is used by Cudd_VerifySol.]
SideEffects [The solution is returned in G; the indices of the y
variables are returned in yIndex.]
SeeAlso [Cudd_VerifySol]
******************************************************************************/
DdNode *
Cudd_SolveEqn(
DdManager * bdd,
DdNode * F /* the left-hand side of the equation */,
DdNode * Y /* the cube of the y variables */,
DdNode ** G /* the array of solutions (return parameter) */,
int ** yIndex /* index of y variables */,
int n /* numbers of unknowns */)
{
DdNode *res;
int *temp;
*yIndex = temp = ALLOC(int, n);
if (temp == NULL) {
bdd->errorCode = CUDD_MEMORY_OUT;
(void) fprintf(bdd->out,
"Cudd_SolveEqn: Out of memory for yIndex\n");
return(NULL);
}
do {
bdd->reordered = 0;
res = cuddSolveEqnRecur(bdd, F, Y, G, n, temp, 0);
} while (bdd->reordered == 1);
return(res);
} /* end of Cudd_SolveEqn */
/**Function********************************************************************
Synopsis [Checks the solution of F(x,y) = 0.]
Description [Checks the solution of F(x,y) = 0. This procedure
substitutes the solution components for the unknowns of F and returns
the resulting BDD for F.]
SideEffects [Frees the memory pointed by yIndex.]
SeeAlso [Cudd_SolveEqn]
******************************************************************************/
DdNode *
Cudd_VerifySol(
DdManager * bdd,
DdNode * F /* the left-hand side of the equation */,
DdNode ** G /* the array of solutions */,
int * yIndex /* index of y variables */,
int n /* numbers of unknowns */)
{
DdNode *res;
do {
bdd->reordered = 0;
res = cuddVerifySol(bdd, F, G, yIndex, n);
} while (bdd->reordered == 1);
FREE(yIndex);
return(res);
} /* end of Cudd_VerifySol */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Implements the recursive step of Cudd_SolveEqn.]
Description [Implements the recursive step of Cudd_SolveEqn.
Returns NULL if the intermediate solution blows up
or reordering occurs. The parametric solutions are
stored in the array G.]
SideEffects [none]
SeeAlso [Cudd_SolveEqn, Cudd_VerifySol]
******************************************************************************/
DdNode *
cuddSolveEqnRecur(
DdManager * bdd,
DdNode * F /* the left-hand side of the equation */,
DdNode * Y /* the cube of remaining y variables */,
DdNode ** G /* the array of solutions */,
int n /* number of unknowns */,
int * yIndex /* array holding the y variable indices */,
int i /* level of recursion */)
{
DdNode *Fn, *Fm1, *Fv, *Fvbar, *T, *w, *nextY, *one;
DdNodePtr *variables;
int j;
statLine(bdd);
variables = bdd->vars;
one = DD_ONE(bdd);
/* Base condition. */
if (Y == one) {
return F;
}
/* Cofactor of Y. */
yIndex[i] = Y->index;
nextY = Cudd_T(Y);
/* Universal abstraction of F with respect to the top variable index. */
Fm1 = cuddBddExistAbstractRecur(bdd, Cudd_Not(F), variables[yIndex[i]]);
if (Fm1) {
Fm1 = Cudd_Not(Fm1);
cuddRef(Fm1);
} else {
return(NULL);
}
Fn = cuddSolveEqnRecur(bdd, Fm1, nextY, G, n, yIndex, i+1);
if (Fn) {
cuddRef(Fn);
} else {
Cudd_RecursiveDeref(bdd, Fm1);
return(NULL);
}
Fv = cuddCofactorRecur(bdd, F, variables[yIndex[i]]);
if (Fv) {
cuddRef(Fv);
} else {
Cudd_RecursiveDeref(bdd, Fm1);
Cudd_RecursiveDeref(bdd, Fn);
return(NULL);
}
Fvbar = cuddCofactorRecur(bdd, F, Cudd_Not(variables[yIndex[i]]));
if (Fvbar) {
cuddRef(Fvbar);
} else {
Cudd_RecursiveDeref(bdd, Fm1);
Cudd_RecursiveDeref(bdd, Fn);
Cudd_RecursiveDeref(bdd, Fv);
return(NULL);
}
/* Build i-th component of the solution. */
w = cuddBddIteRecur(bdd, variables[yIndex[i]], Cudd_Not(Fv), Fvbar);
if (w) {
cuddRef(w);
} else {
Cudd_RecursiveDeref(bdd, Fm1);
Cudd_RecursiveDeref(bdd, Fn);
Cudd_RecursiveDeref(bdd, Fv);
Cudd_RecursiveDeref(bdd, Fvbar);
return(NULL);
}
T = cuddBddRestrictRecur(bdd, w, Cudd_Not(Fm1));
if(T) {
cuddRef(T);
} else {
Cudd_RecursiveDeref(bdd, Fm1);
Cudd_RecursiveDeref(bdd, Fn);
Cudd_RecursiveDeref(bdd, Fv);
Cudd_RecursiveDeref(bdd, Fvbar);
Cudd_RecursiveDeref(bdd, w);
return(NULL);
}
Cudd_RecursiveDeref(bdd,Fm1);
Cudd_RecursiveDeref(bdd,w);
Cudd_RecursiveDeref(bdd,Fv);
Cudd_RecursiveDeref(bdd,Fvbar);
/* Substitute components of solution already found into solution. */
for (j = n-1; j > i; j--) {
w = cuddBddComposeRecur(bdd,T, G[j], variables[yIndex[j]]);
if(w) {
cuddRef(w);
} else {
Cudd_RecursiveDeref(bdd, Fn);
Cudd_RecursiveDeref(bdd, T);
return(NULL);
}
Cudd_RecursiveDeref(bdd,T);
T = w;
}
G[i] = T;
Cudd_Deref(Fn);
return(Fn);
} /* end of cuddSolveEqnRecur */
/**Function********************************************************************
Synopsis [Implements the recursive step of Cudd_VerifySol. ]
Description []
SideEffects [none]
SeeAlso [Cudd_VerifySol]
******************************************************************************/
DdNode *
cuddVerifySol(
DdManager * bdd,
DdNode * F /* the left-hand side of the equation */,
DdNode ** G /* the array of solutions */,
int * yIndex /* array holding the y variable indices */,
int n /* number of unknowns */)
{
DdNode *w, *R;
int j;
R = F;
cuddRef(R);
for(j = n - 1; j >= 0; j--) {
w = Cudd_bddCompose(bdd, R, G[j], yIndex[j]);
if (w) {
cuddRef(w);
} else {
return(NULL);
}
Cudd_RecursiveDeref(bdd,R);
R = w;
}
cuddDeref(R);
return(R);
} /* end of cuddVerifySol */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/

686
cudd_local/cudd/cuddSplit.c Normal file
View File

@@ -0,0 +1,686 @@
/**CFile***********************************************************************
FileName [cuddSplit.c]
PackageName [cudd]
Synopsis [Returns a subset of minterms from a boolean function.]
Description [External functions included in this modoule:
<ul>
<li> Cudd_SplitSet()
</ul>
Internal functions included in this module:
<ul>
<li> cuddSplitSetRecur()
</u>
Static functions included in this module:
<ul>
<li> selectMintermsFromUniverse()
<li> mintermsFromUniverse()
<li> bddAnnotateMintermCount()
</ul> ]
SeeAlso []
Author [Balakrishna Kumthekar]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Structure declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static DdNode * selectMintermsFromUniverse (DdManager *manager, int *varSeen, double n);
static DdNode * mintermsFromUniverse (DdManager *manager, DdNode **vars, int numVars, double n, int index);
static double bddAnnotateMintermCount (DdManager *manager, DdNode *node, double max, st_table *table);
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Returns m minterms from a BDD.]
Description [Returns <code>m</code> minterms from a BDD whose
support has <code>n</code> variables at most. The procedure tries
to create as few extra nodes as possible. The function represented
by <code>S</code> depends on at most <code>n</code> of the variables
in <code>xVars</code>. Returns a BDD with <code>m</code> minterms
of the on-set of S if successful; NULL otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
DdNode *
Cudd_SplitSet(
DdManager * manager,
DdNode * S,
DdNode ** xVars,
int n,
double m)
{
DdNode *result;
DdNode *zero, *one;
double max, num;
st_table *mtable;
int *varSeen;
int i,index, size;
size = manager->size;
one = DD_ONE(manager);
zero = Cudd_Not(one);
/* Trivial cases. */
if (m == 0.0) {
return(zero);
}
if (S == zero) {
return(NULL);
}
max = pow(2.0,(double)n);
if (m > max)
return(NULL);
do {
manager->reordered = 0;
/* varSeen is used to mark the variables that are encountered
** while traversing the BDD S.
*/
varSeen = ALLOC(int, size);
if (varSeen == NULL) {
manager->errorCode = CUDD_MEMORY_OUT;
return(NULL);
}
for (i = 0; i < size; i++) {
varSeen[i] = -1;
}
for (i = 0; i < n; i++) {
index = (xVars[i])->index;
varSeen[manager->invperm[index]] = 0;
}
if (S == one) {
if (m == max) {
FREE(varSeen);
return(S);
}
result = selectMintermsFromUniverse(manager,varSeen,m);
if (result)
cuddRef(result);
FREE(varSeen);
} else {
mtable = st_init_table(st_ptrcmp,st_ptrhash);
if (mtable == NULL) {
(void) fprintf(manager->out,
"Cudd_SplitSet: out-of-memory.\n");
FREE(varSeen);
manager->errorCode = CUDD_MEMORY_OUT;
return(NULL);
}
/* The nodes of BDD S are annotated by the number of minterms
** in their onset. The node and the number of minterms in its
** onset are stored in mtable.
*/
num = bddAnnotateMintermCount(manager,S,max,mtable);
if (m == num) {
st_foreach(mtable,cuddStCountfree,NIL(char));
st_free_table(mtable);
FREE(varSeen);
return(S);
}
result = cuddSplitSetRecur(manager,mtable,varSeen,S,m,max,0);
if (result)
cuddRef(result);
st_foreach(mtable,cuddStCountfree,NULL);
st_free_table(mtable);
FREE(varSeen);
}
} while (manager->reordered == 1);
cuddDeref(result);
return(result);
} /* end of Cudd_SplitSet */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Implements the recursive step of Cudd_SplitSet.]
Description [Implements the recursive step of Cudd_SplitSet. The
procedure recursively traverses the BDD and checks to see if any
node satisfies the minterm requirements as specified by 'n'. At any
node X, n is compared to the number of minterms in the onset of X's
children. If either of the child nodes have exactly n minterms, then
that node is returned; else, if n is greater than the onset of one
of the child nodes, that node is retained and the difference in the
number of minterms is extracted from the other child. In case n
minterms can be extracted from constant 1, the algorithm returns the
result with at most log(n) nodes.]
SideEffects [The array 'varSeen' is updated at every recursive call
to set the variables traversed by the procedure.]
SeeAlso []
******************************************************************************/
DdNode*
cuddSplitSetRecur(
DdManager * manager,
st_table * mtable,
int * varSeen,
DdNode * p,
double n,
double max,
int index)
{
DdNode *one, *zero, *N, *Nv;
DdNode *Nnv, *q, *r, *v;
DdNode *result;
double *dummy, numT, numE;
int variable, positive;
statLine(manager);
one = DD_ONE(manager);
zero = Cudd_Not(one);
/* If p is constant, extract n minterms from constant 1. The procedure by
** construction guarantees that minterms will not be extracted from
** constant 0.
*/
if (Cudd_IsConstant(p)) {
q = selectMintermsFromUniverse(manager,varSeen,n);
return(q);
}
N = Cudd_Regular(p);
/* Set variable as seen. */
variable = N->index;
varSeen[manager->invperm[variable]] = -1;
Nv = cuddT(N);
Nnv = cuddE(N);
if (Cudd_IsComplement(p)) {
Nv = Cudd_Not(Nv);
Nnv = Cudd_Not(Nnv);
}
/* If both the children of 'p' are constants, extract n minterms from a
** constant node.
*/
if (Cudd_IsConstant(Nv) && Cudd_IsConstant(Nnv)) {
q = selectMintermsFromUniverse(manager,varSeen,n);
if (q == NULL) {
return(NULL);
}
cuddRef(q);
r = cuddBddAndRecur(manager,p,q);
if (r == NULL) {
Cudd_RecursiveDeref(manager,q);
return(NULL);
}
cuddRef(r);
Cudd_RecursiveDeref(manager,q);
cuddDeref(r);
return(r);
}
/* Lookup the # of minterms in the onset of the node from the table. */
if (!Cudd_IsConstant(Nv)) {
if (!st_lookup(mtable, Nv, &dummy)) return(NULL);
numT = *dummy/(2*(1<<index));
} else if (Nv == one) {
numT = max/(2*(1<<index));
} else {
numT = 0;
}
if (!Cudd_IsConstant(Nnv)) {
if (!st_lookup(mtable, Nnv, &dummy)) return(NULL);
numE = *dummy/(2*(1<<index));
} else if (Nnv == one) {
numE = max/(2*(1<<index));
} else {
numE = 0;
}
v = cuddUniqueInter(manager,variable,one,zero);
cuddRef(v);
/* If perfect match. */
if (numT == n) {
q = cuddBddAndRecur(manager,v,Nv);
if (q == NULL) {
Cudd_RecursiveDeref(manager,v);
return(NULL);
}
cuddRef(q);
Cudd_RecursiveDeref(manager,v);
cuddDeref(q);
return(q);
}
if (numE == n) {
q = cuddBddAndRecur(manager,Cudd_Not(v),Nnv);
if (q == NULL) {
Cudd_RecursiveDeref(manager,v);
return(NULL);
}
cuddRef(q);
Cudd_RecursiveDeref(manager,v);
cuddDeref(q);
return(q);
}
/* If n is greater than numT, extract the difference from the ELSE child
** and retain the function represented by the THEN branch.
*/
if (numT < n) {
q = cuddSplitSetRecur(manager,mtable,varSeen,
Nnv,(n-numT),max,index+1);
if (q == NULL) {
Cudd_RecursiveDeref(manager,v);
return(NULL);
}
cuddRef(q);
r = cuddBddIteRecur(manager,v,Nv,q);
if (r == NULL) {
Cudd_RecursiveDeref(manager,q);
Cudd_RecursiveDeref(manager,v);
return(NULL);
}
cuddRef(r);
Cudd_RecursiveDeref(manager,q);
Cudd_RecursiveDeref(manager,v);
cuddDeref(r);
return(r);
}
/* If n is greater than numE, extract the difference from the THEN child
** and retain the function represented by the ELSE branch.
*/
if (numE < n) {
q = cuddSplitSetRecur(manager,mtable,varSeen,
Nv, (n-numE),max,index+1);
if (q == NULL) {
Cudd_RecursiveDeref(manager,v);
return(NULL);
}
cuddRef(q);
r = cuddBddIteRecur(manager,v,q,Nnv);
if (r == NULL) {
Cudd_RecursiveDeref(manager,q);
Cudd_RecursiveDeref(manager,v);
return(NULL);
}
cuddRef(r);
Cudd_RecursiveDeref(manager,q);
Cudd_RecursiveDeref(manager,v);
cuddDeref(r);
return(r);
}
/* None of the above cases; (n < numT and n < numE) and either of
** the Nv, Nnv or both are not constants. If possible extract the
** required minterms the constant branch.
*/
if (Cudd_IsConstant(Nv) && !Cudd_IsConstant(Nnv)) {
q = selectMintermsFromUniverse(manager,varSeen,n);
if (q == NULL) {
Cudd_RecursiveDeref(manager,v);
return(NULL);
}
cuddRef(q);
result = cuddBddAndRecur(manager,v,q);
if (result == NULL) {
Cudd_RecursiveDeref(manager,q);
Cudd_RecursiveDeref(manager,v);
return(NULL);
}
cuddRef(result);
Cudd_RecursiveDeref(manager,q);
Cudd_RecursiveDeref(manager,v);
cuddDeref(result);
return(result);
} else if (!Cudd_IsConstant(Nv) && Cudd_IsConstant(Nnv)) {
q = selectMintermsFromUniverse(manager,varSeen,n);
if (q == NULL) {
Cudd_RecursiveDeref(manager,v);
return(NULL);
}
cuddRef(q);
result = cuddBddAndRecur(manager,Cudd_Not(v),q);
if (result == NULL) {
Cudd_RecursiveDeref(manager,q);
Cudd_RecursiveDeref(manager,v);
return(NULL);
}
cuddRef(result);
Cudd_RecursiveDeref(manager,q);
Cudd_RecursiveDeref(manager,v);
cuddDeref(result);
return(result);
}
/* Both Nv and Nnv are not constants. So choose the one which
** has fewer minterms in its onset.
*/
positive = 0;
if (numT < numE) {
q = cuddSplitSetRecur(manager,mtable,varSeen,
Nv,n,max,index+1);
positive = 1;
} else {
q = cuddSplitSetRecur(manager,mtable,varSeen,
Nnv,n,max,index+1);
}
if (q == NULL) {
Cudd_RecursiveDeref(manager,v);
return(NULL);
}
cuddRef(q);
if (positive) {
result = cuddBddAndRecur(manager,v,q);
} else {
result = cuddBddAndRecur(manager,Cudd_Not(v),q);
}
if (result == NULL) {
Cudd_RecursiveDeref(manager,q);
Cudd_RecursiveDeref(manager,v);
return(NULL);
}
cuddRef(result);
Cudd_RecursiveDeref(manager,q);
Cudd_RecursiveDeref(manager,v);
cuddDeref(result);
return(result);
} /* end of cuddSplitSetRecur */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [This function prepares an array of variables which have not been
encountered so far when traversing the procedure cuddSplitSetRecur.]
Description [This function prepares an array of variables which have not been
encountered so far when traversing the procedure cuddSplitSetRecur. This
array is then used to extract the required number of minterms from a constant
1. The algorithm guarantees that the size of BDD will be utmost \log(n).]
SideEffects [None]
******************************************************************************/
static DdNode *
selectMintermsFromUniverse(
DdManager * manager,
int * varSeen,
double n)
{
int numVars;
int i, size, j;
DdNode *one, *zero, *result;
DdNode **vars;
numVars = 0;
size = manager->size;
one = DD_ONE(manager);
zero = Cudd_Not(one);
/* Count the number of variables not encountered so far in procedure
** cuddSplitSetRecur.
*/
for (i = size-1; i >= 0; i--) {
if(varSeen[i] == 0)
numVars++;
}
vars = ALLOC(DdNode *, numVars);
if (!vars) {
manager->errorCode = CUDD_MEMORY_OUT;
return(NULL);
}
j = 0;
for (i = size-1; i >= 0; i--) {
if(varSeen[i] == 0) {
vars[j] = cuddUniqueInter(manager,manager->perm[i],one,zero);
cuddRef(vars[j]);
j++;
}
}
/* Compute a function which has n minterms and depends on at most
** numVars variables.
*/
result = mintermsFromUniverse(manager,vars,numVars,n, 0);
if (result)
cuddRef(result);
for (i = 0; i < numVars; i++)
Cudd_RecursiveDeref(manager,vars[i]);
FREE(vars);
return(result);
} /* end of selectMintermsFromUniverse */
/**Function********************************************************************
Synopsis [Recursive procedure to extract n mintems from constant 1.]
Description [Recursive procedure to extract n mintems from constant 1.]
SideEffects [None]
******************************************************************************/
static DdNode *
mintermsFromUniverse(
DdManager * manager,
DdNode ** vars,
int numVars,
double n,
int index)
{
DdNode *one, *zero;
DdNode *q, *result;
double max, max2;
statLine(manager);
one = DD_ONE(manager);
zero = Cudd_Not(one);
max = pow(2.0, (double)numVars);
max2 = max / 2.0;
if (n == max)
return(one);
if (n == 0.0)
return(zero);
/* if n == 2^(numVars-1), return a single variable */
if (n == max2)
return vars[index];
else if (n > max2) {
/* When n > 2^(numVars-1), a single variable vars[index]
** contains 2^(numVars-1) minterms. The rest are extracted
** from a constant with 1 less variable.
*/
q = mintermsFromUniverse(manager,vars,numVars-1,(n-max2),index+1);
if (q == NULL)
return(NULL);
cuddRef(q);
result = cuddBddIteRecur(manager,vars[index],one,q);
} else {
/* When n < 2^(numVars-1), a literal of variable vars[index]
** is selected. The required n minterms are extracted from a
** constant with 1 less variable.
*/
q = mintermsFromUniverse(manager,vars,numVars-1,n,index+1);
if (q == NULL)
return(NULL);
cuddRef(q);
result = cuddBddAndRecur(manager,vars[index],q);
}
if (result == NULL) {
Cudd_RecursiveDeref(manager,q);
return(NULL);
}
cuddRef(result);
Cudd_RecursiveDeref(manager,q);
cuddDeref(result);
return(result);
} /* end of mintermsFromUniverse */
/**Function********************************************************************
Synopsis [Annotates every node in the BDD node with its minterm count.]
Description [Annotates every node in the BDD node with its minterm count.
In this function, every node and the minterm count represented by it are
stored in a hash table.]
SideEffects [Fills up 'table' with the pair <node,minterm_count>.]
******************************************************************************/
static double
bddAnnotateMintermCount(
DdManager * manager,
DdNode * node,
double max,
st_table * table)
{
DdNode *N,*Nv,*Nnv;
register double min_v,min_nv;
register double min_N;
double *pmin;
double *dummy;
statLine(manager);
N = Cudd_Regular(node);
if (cuddIsConstant(N)) {
if (node == DD_ONE(manager)) {
return(max);
} else {
return(0.0);
}
}
if (st_lookup(table, node, &dummy)) {
return(*dummy);
}
Nv = cuddT(N);
Nnv = cuddE(N);
if (N != node) {
Nv = Cudd_Not(Nv);
Nnv = Cudd_Not(Nnv);
}
/* Recur on the two branches. */
min_v = bddAnnotateMintermCount(manager,Nv,max,table) / 2.0;
if (min_v == (double)CUDD_OUT_OF_MEM)
return ((double)CUDD_OUT_OF_MEM);
min_nv = bddAnnotateMintermCount(manager,Nnv,max,table) / 2.0;
if (min_nv == (double)CUDD_OUT_OF_MEM)
return ((double)CUDD_OUT_OF_MEM);
min_N = min_v + min_nv;
pmin = ALLOC(double,1);
if (pmin == NULL) {
manager->errorCode = CUDD_MEMORY_OUT;
return((double)CUDD_OUT_OF_MEM);
}
*pmin = min_N;
if (st_insert(table,(char *)node, (char *)pmin) == ST_OUT_OF_MEM) {
FREE(pmin);
return((double)CUDD_OUT_OF_MEM);
}
return(min_N);
} /* end of bddAnnotateMintermCount */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3213
cudd_local/cudd/cuddTable.c Normal file

File diff suppressed because it is too large Load Diff

4032
cudd_local/cudd/cuddUtil.c Normal file

File diff suppressed because it is too large Load Diff

1023
cudd_local/cudd/cuddWindow.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,357 @@
/**CFile***********************************************************************
FileName [cuddZddCount.c]
PackageName [cudd]
Synopsis [Procedures to count the number of minterms of a ZDD.]
Description [External procedures included in this module:
<ul>
<li> Cudd_zddCount();
<li> Cudd_zddCountDouble();
</ul>
Internal procedures included in this module:
<ul>
</ul>
Static procedures included in this module:
<ul>
<li> cuddZddCountStep();
<li> cuddZddCountDoubleStep();
<li> st_zdd_count_dbl_free()
<li> st_zdd_countfree()
</ul>
]
SeeAlso []
Author [Hyong-Kyoon Shin, In-Ho Moon]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddZddCount.c,v 1.15 2012/02/05 01:07:19 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static int cuddZddCountStep (DdNode *P, st_table *table, DdNode *base, DdNode *empty);
static double cuddZddCountDoubleStep (DdNode *P, st_table *table, DdNode *base, DdNode *empty);
static enum st_retval st_zdd_countfree (char *key, char *value, char *arg);
static enum st_retval st_zdd_count_dbl_free (char *key, char *value, char *arg);
/**AutomaticEnd***************************************************************/
#ifdef __cplusplus
}
#endif
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Counts the number of minterms in a ZDD.]
Description [Returns an integer representing the number of minterms
in a ZDD.]
SideEffects [None]
SeeAlso [Cudd_zddCountDouble]
******************************************************************************/
int
Cudd_zddCount(
DdManager * zdd,
DdNode * P)
{
st_table *table;
int res;
DdNode *base, *empty;
base = DD_ONE(zdd);
empty = DD_ZERO(zdd);
table = st_init_table(st_ptrcmp, st_ptrhash);
if (table == NULL) return(CUDD_OUT_OF_MEM);
res = cuddZddCountStep(P, table, base, empty);
if (res == CUDD_OUT_OF_MEM) {
zdd->errorCode = CUDD_MEMORY_OUT;
}
st_foreach(table, st_zdd_countfree, NIL(char));
st_free_table(table);
return(res);
} /* end of Cudd_zddCount */
/**Function********************************************************************
Synopsis [Counts the number of minterms of a ZDD.]
Description [Counts the number of minterms of a ZDD. The result is
returned as a double. If the procedure runs out of memory, it
returns (double) CUDD_OUT_OF_MEM. This procedure is used in
Cudd_zddCountMinterm.]
SideEffects [None]
SeeAlso [Cudd_zddCountMinterm Cudd_zddCount]
******************************************************************************/
double
Cudd_zddCountDouble(
DdManager * zdd,
DdNode * P)
{
st_table *table;
double res;
DdNode *base, *empty;
base = DD_ONE(zdd);
empty = DD_ZERO(zdd);
table = st_init_table(st_ptrcmp, st_ptrhash);
if (table == NULL) return((double)CUDD_OUT_OF_MEM);
res = cuddZddCountDoubleStep(P, table, base, empty);
if (res == (double)CUDD_OUT_OF_MEM) {
zdd->errorCode = CUDD_MEMORY_OUT;
}
st_foreach(table, st_zdd_count_dbl_free, NIL(char));
st_free_table(table);
return(res);
} /* end of Cudd_zddCountDouble */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddCount.]
Description []
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
cuddZddCountStep(
DdNode * P,
st_table * table,
DdNode * base,
DdNode * empty)
{
int res;
int *dummy;
if (P == empty)
return(0);
if (P == base)
return(1);
/* Check cache. */
if (st_lookup(table, P, &dummy)) {
res = *dummy;
return(res);
}
res = cuddZddCountStep(cuddE(P), table, base, empty) +
cuddZddCountStep(cuddT(P), table, base, empty);
dummy = ALLOC(int, 1);
if (dummy == NULL) {
return(CUDD_OUT_OF_MEM);
}
*dummy = res;
if (st_insert(table, (char *)P, (char *)dummy) == ST_OUT_OF_MEM) {
FREE(dummy);
return(CUDD_OUT_OF_MEM);
}
return(res);
} /* end of cuddZddCountStep */
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddCountDouble.]
Description []
SideEffects [None]
SeeAlso []
******************************************************************************/
static double
cuddZddCountDoubleStep(
DdNode * P,
st_table * table,
DdNode * base,
DdNode * empty)
{
double res;
double *dummy;
if (P == empty)
return((double)0.0);
if (P == base)
return((double)1.0);
/* Check cache */
if (st_lookup(table, P, &dummy)) {
res = *dummy;
return(res);
}
res = cuddZddCountDoubleStep(cuddE(P), table, base, empty) +
cuddZddCountDoubleStep(cuddT(P), table, base, empty);
dummy = ALLOC(double, 1);
if (dummy == NULL) {
return((double)CUDD_OUT_OF_MEM);
}
*dummy = res;
if (st_insert(table, (char *)P, (char *)dummy) == ST_OUT_OF_MEM) {
FREE(dummy);
return((double)CUDD_OUT_OF_MEM);
}
return(res);
} /* end of cuddZddCountDoubleStep */
/**Function********************************************************************
Synopsis [Frees the memory associated with the computed table of
Cudd_zddCount.]
Description []
SideEffects [None]
SeeAlso []
******************************************************************************/
static enum st_retval
st_zdd_countfree(
char * key,
char * value,
char * arg)
{
int *d;
d = (int *)value;
FREE(d);
return(ST_CONTINUE);
} /* end of st_zdd_countfree */
/**Function********************************************************************
Synopsis [Frees the memory associated with the computed table of
Cudd_zddCountDouble.]
Description []
SideEffects [None]
SeeAlso []
******************************************************************************/
static enum st_retval
st_zdd_count_dbl_free(
char * key,
char * value,
char * arg)
{
double *d;
d = (double *)value;
FREE(d);
return(ST_CONTINUE);
} /* end of st_zdd_count_dbl_free */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,912 @@
/**CFile***********************************************************************
FileName [cuddZddIsop.c]
PackageName [cudd]
Synopsis [Functions to find irredundant SOP covers as ZDDs from BDDs.]
Description [External procedures included in this module:
<ul>
<li> Cudd_bddIsop()
<li> Cudd_zddIsop()
<li> Cudd_MakeBddFromZddCover()
</ul>
Internal procedures included in this module:
<ul>
<li> cuddBddIsop()
<li> cuddZddIsop()
<li> cuddMakeBddFromZddCover()
</ul>
Static procedures included in this module:
<ul>
</ul>
]
SeeAlso []
Author [In-Ho Moon]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddZddIsop.c,v 1.22 2012/02/05 01:07:19 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Computes an ISOP in ZDD form from BDDs.]
Description [Computes an irredundant sum of products (ISOP) in ZDD
form from BDDs. The two BDDs L and U represent the lower bound and
the upper bound, respectively, of the function. The ISOP uses two
ZDD variables for each BDD variable: One for the positive literal,
and one for the negative literal. These two variables should be
adjacent in the ZDD order. The two ZDD variables corresponding to
BDD variable <code>i</code> should have indices <code>2i</code> and
<code>2i+1</code>. The result of this procedure depends on the
variable order. If successful, Cudd_zddIsop returns the BDD for
the function chosen from the interval. The ZDD representing the
irredundant cover is returned as a side effect in zdd_I. In case of
failure, NULL is returned.]
SideEffects [zdd_I holds the pointer to the ZDD for the ISOP on
successful return.]
SeeAlso [Cudd_bddIsop Cudd_zddVarsFromBddVars]
******************************************************************************/
DdNode *
Cudd_zddIsop(
DdManager * dd,
DdNode * L,
DdNode * U,
DdNode ** zdd_I)
{
DdNode *res;
int autoDynZ;
autoDynZ = dd->autoDynZ;
dd->autoDynZ = 0;
do {
dd->reordered = 0;
res = cuddZddIsop(dd, L, U, zdd_I);
} while (dd->reordered == 1);
dd->autoDynZ = autoDynZ;
return(res);
} /* end of Cudd_zddIsop */
/**Function********************************************************************
Synopsis [Computes a BDD in the interval between L and U with a
simple sum-of-product cover.]
Description [Computes a BDD in the interval between L and U with a
simple sum-of-product cover. This procedure is similar to
Cudd_zddIsop, but it does not return the ZDD for the cover. Returns
a pointer to the BDD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_zddIsop]
******************************************************************************/
DdNode *
Cudd_bddIsop(
DdManager * dd,
DdNode * L,
DdNode * U)
{
DdNode *res;
do {
dd->reordered = 0;
res = cuddBddIsop(dd, L, U);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_bddIsop */
/**Function********************************************************************
Synopsis [Converts a ZDD cover to a BDD.]
Description [Converts a ZDD cover to a BDD for the function represented
by the cover. If successful, it returns a BDD node, otherwise it returns
NULL.]
SideEffects []
SeeAlso [Cudd_zddIsop]
******************************************************************************/
DdNode *
Cudd_MakeBddFromZddCover(
DdManager * dd,
DdNode * node)
{
DdNode *res;
do {
dd->reordered = 0;
res = cuddMakeBddFromZddCover(dd, node);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_MakeBddFromZddCover */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddIsop.]
Description []
SideEffects [None]
SeeAlso [Cudd_zddIsop]
******************************************************************************/
DdNode *
cuddZddIsop(
DdManager * dd,
DdNode * L,
DdNode * U,
DdNode ** zdd_I)
{
DdNode *one = DD_ONE(dd);
DdNode *zero = Cudd_Not(one);
DdNode *zdd_one = DD_ONE(dd);
DdNode *zdd_zero = DD_ZERO(dd);
int v, top_l, top_u;
DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud;
DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1;
DdNode *Isub0, *Isub1, *Id;
DdNode *zdd_Isub0, *zdd_Isub1, *zdd_Id;
DdNode *x;
DdNode *term0, *term1, *sum;
DdNode *Lv, *Uv, *Lnv, *Unv;
DdNode *r, *y, *z;
int index;
DD_CTFP cacheOp;
statLine(dd);
if (L == zero) {
*zdd_I = zdd_zero;
return(zero);
}
if (U == one) {
*zdd_I = zdd_one;
return(one);
}
if (U == zero || L == one) {
printf("*** ERROR : illegal condition for ISOP (U < L).\n");
exit(1);
}
/* Check the cache. We store two results for each recursive call.
** One is the BDD, and the other is the ZDD. Both are needed.
** Hence we need a double hit in the cache to terminate the
** recursion. Clearly, collisions may evict only one of the two
** results. */
cacheOp = (DD_CTFP) cuddZddIsop;
r = cuddCacheLookup2(dd, cuddBddIsop, L, U);
if (r) {
*zdd_I = cuddCacheLookup2Zdd(dd, cacheOp, L, U);
if (*zdd_I)
return(r);
else {
/* The BDD result may have been dead. In that case
** cuddCacheLookup2 would have called cuddReclaim,
** whose effects we now have to undo. */
cuddRef(r);
Cudd_RecursiveDeref(dd, r);
}
}
top_l = dd->perm[Cudd_Regular(L)->index];
top_u = dd->perm[Cudd_Regular(U)->index];
v = ddMin(top_l, top_u);
/* Compute cofactors. */
if (top_l == v) {
index = Cudd_Regular(L)->index;
Lv = Cudd_T(L);
Lnv = Cudd_E(L);
if (Cudd_IsComplement(L)) {
Lv = Cudd_Not(Lv);
Lnv = Cudd_Not(Lnv);
}
}
else {
index = Cudd_Regular(U)->index;
Lv = Lnv = L;
}
if (top_u == v) {
Uv = Cudd_T(U);
Unv = Cudd_E(U);
if (Cudd_IsComplement(U)) {
Uv = Cudd_Not(Uv);
Unv = Cudd_Not(Unv);
}
}
else {
Uv = Unv = U;
}
Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv));
if (Lsub0 == NULL)
return(NULL);
Cudd_Ref(Lsub0);
Usub0 = Unv;
Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv));
if (Lsub1 == NULL) {
Cudd_RecursiveDeref(dd, Lsub0);
return(NULL);
}
Cudd_Ref(Lsub1);
Usub1 = Uv;
Isub0 = cuddZddIsop(dd, Lsub0, Usub0, &zdd_Isub0);
if (Isub0 == NULL) {
Cudd_RecursiveDeref(dd, Lsub0);
Cudd_RecursiveDeref(dd, Lsub1);
return(NULL);
}
/*
if ((!cuddIsConstant(Cudd_Regular(Isub0))) &&
(Cudd_Regular(Isub0)->index != zdd_Isub0->index / 2 ||
dd->permZ[index * 2] > dd->permZ[zdd_Isub0->index])) {
printf("*** ERROR : illegal permutation in ZDD. ***\n");
}
*/
Cudd_Ref(Isub0);
Cudd_Ref(zdd_Isub0);
Isub1 = cuddZddIsop(dd, Lsub1, Usub1, &zdd_Isub1);
if (Isub1 == NULL) {
Cudd_RecursiveDeref(dd, Lsub0);
Cudd_RecursiveDeref(dd, Lsub1);
Cudd_RecursiveDeref(dd, Isub0);
Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
return(NULL);
}
/*
if ((!cuddIsConstant(Cudd_Regular(Isub1))) &&
(Cudd_Regular(Isub1)->index != zdd_Isub1->index / 2 ||
dd->permZ[index * 2] > dd->permZ[zdd_Isub1->index])) {
printf("*** ERROR : illegal permutation in ZDD. ***\n");
}
*/
Cudd_Ref(Isub1);
Cudd_Ref(zdd_Isub1);
Cudd_RecursiveDeref(dd, Lsub0);
Cudd_RecursiveDeref(dd, Lsub1);
Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0));
if (Lsuper0 == NULL) {
Cudd_RecursiveDeref(dd, Isub0);
Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
Cudd_RecursiveDeref(dd, Isub1);
Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
return(NULL);
}
Cudd_Ref(Lsuper0);
Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1));
if (Lsuper1 == NULL) {
Cudd_RecursiveDeref(dd, Isub0);
Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
Cudd_RecursiveDeref(dd, Isub1);
Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
Cudd_RecursiveDeref(dd, Lsuper0);
return(NULL);
}
Cudd_Ref(Lsuper1);
Usuper0 = Unv;
Usuper1 = Uv;
/* Ld = Lsuper0 + Lsuper1 */
Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1));
if (Ld == NULL) {
Cudd_RecursiveDeref(dd, Isub0);
Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
Cudd_RecursiveDeref(dd, Isub1);
Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
Cudd_RecursiveDeref(dd, Lsuper0);
Cudd_RecursiveDeref(dd, Lsuper1);
return(NULL);
}
Ld = Cudd_Not(Ld);
Cudd_Ref(Ld);
/* Ud = Usuper0 * Usuper1 */
Ud = cuddBddAndRecur(dd, Usuper0, Usuper1);
if (Ud == NULL) {
Cudd_RecursiveDeref(dd, Isub0);
Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
Cudd_RecursiveDeref(dd, Isub1);
Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
Cudd_RecursiveDeref(dd, Lsuper0);
Cudd_RecursiveDeref(dd, Lsuper1);
Cudd_RecursiveDeref(dd, Ld);
return(NULL);
}
Cudd_Ref(Ud);
Cudd_RecursiveDeref(dd, Lsuper0);
Cudd_RecursiveDeref(dd, Lsuper1);
Id = cuddZddIsop(dd, Ld, Ud, &zdd_Id);
if (Id == NULL) {
Cudd_RecursiveDeref(dd, Isub0);
Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
Cudd_RecursiveDeref(dd, Isub1);
Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
Cudd_RecursiveDeref(dd, Ld);
Cudd_RecursiveDeref(dd, Ud);
return(NULL);
}
/*
if ((!cuddIsConstant(Cudd_Regular(Id))) &&
(Cudd_Regular(Id)->index != zdd_Id->index / 2 ||
dd->permZ[index * 2] > dd->permZ[zdd_Id->index])) {
printf("*** ERROR : illegal permutation in ZDD. ***\n");
}
*/
Cudd_Ref(Id);
Cudd_Ref(zdd_Id);
Cudd_RecursiveDeref(dd, Ld);
Cudd_RecursiveDeref(dd, Ud);
x = cuddUniqueInter(dd, index, one, zero);
if (x == NULL) {
Cudd_RecursiveDeref(dd, Isub0);
Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
Cudd_RecursiveDeref(dd, Isub1);
Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
Cudd_RecursiveDeref(dd, Id);
Cudd_RecursiveDerefZdd(dd, zdd_Id);
return(NULL);
}
Cudd_Ref(x);
/* term0 = x * Isub0 */
term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0);
if (term0 == NULL) {
Cudd_RecursiveDeref(dd, Isub0);
Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
Cudd_RecursiveDeref(dd, Isub1);
Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
Cudd_RecursiveDeref(dd, Id);
Cudd_RecursiveDerefZdd(dd, zdd_Id);
Cudd_RecursiveDeref(dd, x);
return(NULL);
}
Cudd_Ref(term0);
Cudd_RecursiveDeref(dd, Isub0);
/* term1 = x * Isub1 */
term1 = cuddBddAndRecur(dd, x, Isub1);
if (term1 == NULL) {
Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
Cudd_RecursiveDeref(dd, Isub1);
Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
Cudd_RecursiveDeref(dd, Id);
Cudd_RecursiveDerefZdd(dd, zdd_Id);
Cudd_RecursiveDeref(dd, x);
Cudd_RecursiveDeref(dd, term0);
return(NULL);
}
Cudd_Ref(term1);
Cudd_RecursiveDeref(dd, x);
Cudd_RecursiveDeref(dd, Isub1);
/* sum = term0 + term1 */
sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1));
if (sum == NULL) {
Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
Cudd_RecursiveDeref(dd, Id);
Cudd_RecursiveDerefZdd(dd, zdd_Id);
Cudd_RecursiveDeref(dd, term0);
Cudd_RecursiveDeref(dd, term1);
return(NULL);
}
sum = Cudd_Not(sum);
Cudd_Ref(sum);
Cudd_RecursiveDeref(dd, term0);
Cudd_RecursiveDeref(dd, term1);
/* r = sum + Id */
r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id));
r = Cudd_NotCond(r, r != NULL);
if (r == NULL) {
Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
Cudd_RecursiveDeref(dd, Id);
Cudd_RecursiveDerefZdd(dd, zdd_Id);
Cudd_RecursiveDeref(dd, sum);
return(NULL);
}
Cudd_Ref(r);
Cudd_RecursiveDeref(dd, sum);
Cudd_RecursiveDeref(dd, Id);
if (zdd_Isub0 != zdd_zero) {
z = cuddZddGetNodeIVO(dd, index * 2 + 1, zdd_Isub0, zdd_Id);
if (z == NULL) {
Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
Cudd_RecursiveDerefZdd(dd, zdd_Id);
Cudd_RecursiveDeref(dd, r);
return(NULL);
}
}
else {
z = zdd_Id;
}
Cudd_Ref(z);
if (zdd_Isub1 != zdd_zero) {
y = cuddZddGetNodeIVO(dd, index * 2, zdd_Isub1, z);
if (y == NULL) {
Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
Cudd_RecursiveDerefZdd(dd, zdd_Id);
Cudd_RecursiveDeref(dd, r);
Cudd_RecursiveDerefZdd(dd, z);
return(NULL);
}
}
else
y = z;
Cudd_Ref(y);
Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
Cudd_RecursiveDerefZdd(dd, zdd_Id);
Cudd_RecursiveDerefZdd(dd, z);
cuddCacheInsert2(dd, cuddBddIsop, L, U, r);
cuddCacheInsert2(dd, cacheOp, L, U, y);
Cudd_Deref(r);
Cudd_Deref(y);
*zdd_I = y;
/*
if (Cudd_Regular(r)->index != y->index / 2) {
printf("*** ERROR : mismatch in indices between BDD and ZDD. ***\n");
}
*/
return(r);
} /* end of cuddZddIsop */
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_bddIsop.]
Description []
SideEffects [None]
SeeAlso [Cudd_bddIsop]
******************************************************************************/
DdNode *
cuddBddIsop(
DdManager * dd,
DdNode * L,
DdNode * U)
{
DdNode *one = DD_ONE(dd);
DdNode *zero = Cudd_Not(one);
int v, top_l, top_u;
DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud;
DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1;
DdNode *Isub0, *Isub1, *Id;
DdNode *x;
DdNode *term0, *term1, *sum;
DdNode *Lv, *Uv, *Lnv, *Unv;
DdNode *r;
int index;
statLine(dd);
if (L == zero)
return(zero);
if (U == one)
return(one);
/* Check cache */
r = cuddCacheLookup2(dd, cuddBddIsop, L, U);
if (r)
return(r);
top_l = dd->perm[Cudd_Regular(L)->index];
top_u = dd->perm[Cudd_Regular(U)->index];
v = ddMin(top_l, top_u);
/* Compute cofactors */
if (top_l == v) {
index = Cudd_Regular(L)->index;
Lv = Cudd_T(L);
Lnv = Cudd_E(L);
if (Cudd_IsComplement(L)) {
Lv = Cudd_Not(Lv);
Lnv = Cudd_Not(Lnv);
}
}
else {
index = Cudd_Regular(U)->index;
Lv = Lnv = L;
}
if (top_u == v) {
Uv = Cudd_T(U);
Unv = Cudd_E(U);
if (Cudd_IsComplement(U)) {
Uv = Cudd_Not(Uv);
Unv = Cudd_Not(Unv);
}
}
else {
Uv = Unv = U;
}
Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv));
if (Lsub0 == NULL)
return(NULL);
Cudd_Ref(Lsub0);
Usub0 = Unv;
Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv));
if (Lsub1 == NULL) {
Cudd_RecursiveDeref(dd, Lsub0);
return(NULL);
}
Cudd_Ref(Lsub1);
Usub1 = Uv;
Isub0 = cuddBddIsop(dd, Lsub0, Usub0);
if (Isub0 == NULL) {
Cudd_RecursiveDeref(dd, Lsub0);
Cudd_RecursiveDeref(dd, Lsub1);
return(NULL);
}
Cudd_Ref(Isub0);
Isub1 = cuddBddIsop(dd, Lsub1, Usub1);
if (Isub1 == NULL) {
Cudd_RecursiveDeref(dd, Lsub0);
Cudd_RecursiveDeref(dd, Lsub1);
Cudd_RecursiveDeref(dd, Isub0);
return(NULL);
}
Cudd_Ref(Isub1);
Cudd_RecursiveDeref(dd, Lsub0);
Cudd_RecursiveDeref(dd, Lsub1);
Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0));
if (Lsuper0 == NULL) {
Cudd_RecursiveDeref(dd, Isub0);
Cudd_RecursiveDeref(dd, Isub1);
return(NULL);
}
Cudd_Ref(Lsuper0);
Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1));
if (Lsuper1 == NULL) {
Cudd_RecursiveDeref(dd, Isub0);
Cudd_RecursiveDeref(dd, Isub1);
Cudd_RecursiveDeref(dd, Lsuper0);
return(NULL);
}
Cudd_Ref(Lsuper1);
Usuper0 = Unv;
Usuper1 = Uv;
/* Ld = Lsuper0 + Lsuper1 */
Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1));
Ld = Cudd_NotCond(Ld, Ld != NULL);
if (Ld == NULL) {
Cudd_RecursiveDeref(dd, Isub0);
Cudd_RecursiveDeref(dd, Isub1);
Cudd_RecursiveDeref(dd, Lsuper0);
Cudd_RecursiveDeref(dd, Lsuper1);
return(NULL);
}
Cudd_Ref(Ld);
Ud = cuddBddAndRecur(dd, Usuper0, Usuper1);
if (Ud == NULL) {
Cudd_RecursiveDeref(dd, Isub0);
Cudd_RecursiveDeref(dd, Isub1);
Cudd_RecursiveDeref(dd, Lsuper0);
Cudd_RecursiveDeref(dd, Lsuper1);
Cudd_RecursiveDeref(dd, Ld);
return(NULL);
}
Cudd_Ref(Ud);
Cudd_RecursiveDeref(dd, Lsuper0);
Cudd_RecursiveDeref(dd, Lsuper1);
Id = cuddBddIsop(dd, Ld, Ud);
if (Id == NULL) {
Cudd_RecursiveDeref(dd, Isub0);
Cudd_RecursiveDeref(dd, Isub1);
Cudd_RecursiveDeref(dd, Ld);
Cudd_RecursiveDeref(dd, Ud);
return(NULL);
}
Cudd_Ref(Id);
Cudd_RecursiveDeref(dd, Ld);
Cudd_RecursiveDeref(dd, Ud);
x = cuddUniqueInter(dd, index, one, zero);
if (x == NULL) {
Cudd_RecursiveDeref(dd, Isub0);
Cudd_RecursiveDeref(dd, Isub1);
Cudd_RecursiveDeref(dd, Id);
return(NULL);
}
Cudd_Ref(x);
term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0);
if (term0 == NULL) {
Cudd_RecursiveDeref(dd, Isub0);
Cudd_RecursiveDeref(dd, Isub1);
Cudd_RecursiveDeref(dd, Id);
Cudd_RecursiveDeref(dd, x);
return(NULL);
}
Cudd_Ref(term0);
Cudd_RecursiveDeref(dd, Isub0);
term1 = cuddBddAndRecur(dd, x, Isub1);
if (term1 == NULL) {
Cudd_RecursiveDeref(dd, Isub1);
Cudd_RecursiveDeref(dd, Id);
Cudd_RecursiveDeref(dd, x);
Cudd_RecursiveDeref(dd, term0);
return(NULL);
}
Cudd_Ref(term1);
Cudd_RecursiveDeref(dd, x);
Cudd_RecursiveDeref(dd, Isub1);
/* sum = term0 + term1 */
sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1));
sum = Cudd_NotCond(sum, sum != NULL);
if (sum == NULL) {
Cudd_RecursiveDeref(dd, Id);
Cudd_RecursiveDeref(dd, term0);
Cudd_RecursiveDeref(dd, term1);
return(NULL);
}
Cudd_Ref(sum);
Cudd_RecursiveDeref(dd, term0);
Cudd_RecursiveDeref(dd, term1);
/* r = sum + Id */
r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id));
r = Cudd_NotCond(r, r != NULL);
if (r == NULL) {
Cudd_RecursiveDeref(dd, Id);
Cudd_RecursiveDeref(dd, sum);
return(NULL);
}
Cudd_Ref(r);
Cudd_RecursiveDeref(dd, sum);
Cudd_RecursiveDeref(dd, Id);
cuddCacheInsert2(dd, cuddBddIsop, L, U, r);
Cudd_Deref(r);
return(r);
} /* end of cuddBddIsop */
/**Function********************************************************************
Synopsis [Converts a ZDD cover to a BDD.]
Description [Converts a ZDD cover to a BDD. If successful, it returns
a BDD node, otherwise it returns NULL. It is a recursive algorithm
that works as follows. First it computes 3 cofactors of a ZDD cover:
f1, f0 and fd. Second, it compute BDDs (b1, b0 and bd) of f1, f0 and fd.
Third, it computes T=b1+bd and E=b0+bd. Fourth, it computes ITE(v,T,E) where
v is the variable which has the index of the top node of the ZDD cover.
In this case, since the index of v can be larger than either the one of T
or the one of E, cuddUniqueInterIVO is called, where IVO stands for
independent from variable ordering.]
SideEffects []
SeeAlso [Cudd_MakeBddFromZddCover]
******************************************************************************/
DdNode *
cuddMakeBddFromZddCover(
DdManager * dd,
DdNode * node)
{
DdNode *neW;
int v;
DdNode *f1, *f0, *fd;
DdNode *b1, *b0, *bd;
DdNode *T, *E;
statLine(dd);
if (node == dd->one)
return(dd->one);
if (node == dd->zero)
return(Cudd_Not(dd->one));
/* Check cache */
neW = cuddCacheLookup1(dd, cuddMakeBddFromZddCover, node);
if (neW)
return(neW);
v = Cudd_Regular(node)->index; /* either yi or zi */
if (cuddZddGetCofactors3(dd, node, v, &f1, &f0, &fd)) return(NULL);
Cudd_Ref(f1);
Cudd_Ref(f0);
Cudd_Ref(fd);
b1 = cuddMakeBddFromZddCover(dd, f1);
if (!b1) {
Cudd_RecursiveDerefZdd(dd, f1);
Cudd_RecursiveDerefZdd(dd, f0);
Cudd_RecursiveDerefZdd(dd, fd);
return(NULL);
}
Cudd_Ref(b1);
b0 = cuddMakeBddFromZddCover(dd, f0);
if (!b0) {
Cudd_RecursiveDerefZdd(dd, f1);
Cudd_RecursiveDerefZdd(dd, f0);
Cudd_RecursiveDerefZdd(dd, fd);
Cudd_RecursiveDeref(dd, b1);
return(NULL);
}
Cudd_Ref(b0);
Cudd_RecursiveDerefZdd(dd, f1);
Cudd_RecursiveDerefZdd(dd, f0);
if (fd != dd->zero) {
bd = cuddMakeBddFromZddCover(dd, fd);
if (!bd) {
Cudd_RecursiveDerefZdd(dd, fd);
Cudd_RecursiveDeref(dd, b1);
Cudd_RecursiveDeref(dd, b0);
return(NULL);
}
Cudd_Ref(bd);
Cudd_RecursiveDerefZdd(dd, fd);
T = cuddBddAndRecur(dd, Cudd_Not(b1), Cudd_Not(bd));
if (!T) {
Cudd_RecursiveDeref(dd, b1);
Cudd_RecursiveDeref(dd, b0);
Cudd_RecursiveDeref(dd, bd);
return(NULL);
}
T = Cudd_NotCond(T, T != NULL);
Cudd_Ref(T);
Cudd_RecursiveDeref(dd, b1);
E = cuddBddAndRecur(dd, Cudd_Not(b0), Cudd_Not(bd));
if (!E) {
Cudd_RecursiveDeref(dd, b0);
Cudd_RecursiveDeref(dd, bd);
Cudd_RecursiveDeref(dd, T);
return(NULL);
}
E = Cudd_NotCond(E, E != NULL);
Cudd_Ref(E);
Cudd_RecursiveDeref(dd, b0);
Cudd_RecursiveDeref(dd, bd);
}
else {
Cudd_RecursiveDerefZdd(dd, fd);
T = b1;
E = b0;
}
if (Cudd_IsComplement(T)) {
neW = cuddUniqueInterIVO(dd, v / 2, Cudd_Not(T), Cudd_Not(E));
if (!neW) {
Cudd_RecursiveDeref(dd, T);
Cudd_RecursiveDeref(dd, E);
return(NULL);
}
neW = Cudd_Not(neW);
}
else {
neW = cuddUniqueInterIVO(dd, v / 2, T, E);
if (!neW) {
Cudd_RecursiveDeref(dd, T);
Cudd_RecursiveDeref(dd, E);
return(NULL);
}
}
Cudd_Ref(neW);
Cudd_RecursiveDeref(dd, T);
Cudd_RecursiveDeref(dd, E);
cuddCacheInsert1(dd, cuddMakeBddFromZddCover, node, neW);
Cudd_Deref(neW);
return(neW);
} /* end of cuddMakeBddFromZddCover */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/

View File

@@ -0,0 +1,971 @@
/**CFile***********************************************************************
FileName [cuddZddLin.c]
PackageName [cudd]
Synopsis [Procedures for dynamic variable ordering of ZDDs.]
Description [Internal procedures included in this module:
<ul>
<li> cuddZddLinearSifting()
</ul>
Static procedures included in this module:
<ul>
<li> cuddZddLinearInPlace()
<li> cuddZddLinerAux()
<li> cuddZddLinearUp()
<li> cuddZddLinearDown()
<li> cuddZddLinearBackward()
<li> cuddZddUndoMoves()
</ul>
]
SeeAlso [cuddLinear.c cuddZddReord.c]
Author [Fabio Somenzi]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
#define CUDD_SWAP_MOVE 0
#define CUDD_LINEAR_TRANSFORM_MOVE 1
#define CUDD_INVERSE_TRANSFORM_MOVE 2
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddZddLin.c,v 1.16 2012/02/05 01:07:19 fabio Exp $";
#endif
extern int *zdd_entry;
extern int zddTotalNumberSwapping;
static int zddTotalNumberLinearTr;
static DdNode *empty;
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static int cuddZddLinearInPlace (DdManager * table, int x, int y);
static int cuddZddLinearAux (DdManager *table, int x, int xLow, int xHigh);
static Move * cuddZddLinearUp (DdManager *table, int y, int xLow, Move *prevMoves);
static Move * cuddZddLinearDown (DdManager *table, int x, int xHigh, Move *prevMoves);
static int cuddZddLinearBackward (DdManager *table, int size, Move *moves);
static Move* cuddZddUndoMoves (DdManager *table, Move *moves);
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Implementation of the linear sifting algorithm for ZDDs.]
Description [Implementation of the linear sifting algorithm for ZDDs.
Assumes that no dead nodes are present.
<ol>
<li> Order all the variables according to the number of entries
in each unique table.
<li> Sift the variable up and down and applies the XOR transformation,
remembering each time the total size of the DD heap.
<li> Select the best permutation.
<li> Repeat 3 and 4 for all variables.
</ol>
Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
int
cuddZddLinearSifting(
DdManager * table,
int lower,
int upper)
{
int i;
int *var;
int size;
int x;
int result;
#ifdef DD_STATS
int previousSize;
#endif
size = table->sizeZ;
empty = table->zero;
/* Find order in which to sift variables. */
var = NULL;
zdd_entry = ALLOC(int, size);
if (zdd_entry == NULL) {
table->errorCode = CUDD_MEMORY_OUT;
goto cuddZddSiftingOutOfMem;
}
var = ALLOC(int, size);
if (var == NULL) {
table->errorCode = CUDD_MEMORY_OUT;
goto cuddZddSiftingOutOfMem;
}
for (i = 0; i < size; i++) {
x = table->permZ[i];
zdd_entry[i] = table->subtableZ[x].keys;
var[i] = i;
}
qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
/* Now sift. */
for (i = 0; i < ddMin(table->siftMaxVar, size); i++) {
if (zddTotalNumberSwapping >= table->siftMaxSwap)
break;
if (util_cpu_time() - table->startTime > table->timeLimit) {
table->autoDynZ = 0; /* prevent further reordering */
break;
}
x = table->permZ[var[i]];
if (x < lower || x > upper) continue;
#ifdef DD_STATS
previousSize = table->keysZ;
#endif
result = cuddZddLinearAux(table, x, lower, upper);
if (!result)
goto cuddZddSiftingOutOfMem;
#ifdef DD_STATS
if (table->keysZ < (unsigned) previousSize) {
(void) fprintf(table->out,"-");
} else if (table->keysZ > (unsigned) previousSize) {
(void) fprintf(table->out,"+"); /* should never happen */
(void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]);
} else {
(void) fprintf(table->out,"=");
}
fflush(table->out);
#endif
}
FREE(var);
FREE(zdd_entry);
return(1);
cuddZddSiftingOutOfMem:
if (zdd_entry != NULL) FREE(zdd_entry);
if (var != NULL) FREE(var);
return(0);
} /* end of cuddZddLinearSifting */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Linearly combines two adjacent variables.]
Description [Linearly combines two adjacent variables. It assumes
that no dead nodes are present on entry to this procedure. The
procedure then guarantees that no dead nodes will be present when it
terminates. cuddZddLinearInPlace assumes that x &lt; y. Returns the
number of keys in the table if successful; 0 otherwise.]
SideEffects [None]
SeeAlso [cuddZddSwapInPlace cuddLinearInPlace]
******************************************************************************/
static int
cuddZddLinearInPlace(
DdManager * table,
int x,
int y)
{
DdNodePtr *xlist, *ylist;
int xindex, yindex;
int xslots, yslots;
int xshift, yshift;
int oldxkeys, oldykeys;
int newxkeys, newykeys;
int i;
int posn;
DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00;
DdNode *newf1, *newf0, *g, *next, *previous;
DdNode *special;
#ifdef DD_DEBUG
assert(x < y);
assert(cuddZddNextHigh(table,x) == y);
assert(table->subtableZ[x].keys != 0);
assert(table->subtableZ[y].keys != 0);
assert(table->subtableZ[x].dead == 0);
assert(table->subtableZ[y].dead == 0);
#endif
zddTotalNumberLinearTr++;
/* Get parameters of x subtable. */
xindex = table->invpermZ[x];
xlist = table->subtableZ[x].nodelist;
oldxkeys = table->subtableZ[x].keys;
xslots = table->subtableZ[x].slots;
xshift = table->subtableZ[x].shift;
newxkeys = 0;
/* Get parameters of y subtable. */
yindex = table->invpermZ[y];
ylist = table->subtableZ[y].nodelist;
oldykeys = table->subtableZ[y].keys;
yslots = table->subtableZ[y].slots;
yshift = table->subtableZ[y].shift;
newykeys = oldykeys;
/* The nodes in the x layer are put in two chains. The chain
** pointed by g holds the normal nodes. When re-expressed they stay
** in the x list. The chain pointed by special holds the elements
** that will move to the y list.
*/
g = special = NULL;
for (i = 0; i < xslots; i++) {
f = xlist[i];
if (f == NULL) continue;
xlist[i] = NULL;
while (f != NULL) {
next = f->next;
f1 = cuddT(f);
/* if (f1->index == yindex) */ cuddSatDec(f1->ref);
f0 = cuddE(f);
/* if (f0->index == yindex) */ cuddSatDec(f0->ref);
if ((int) f1->index == yindex && cuddE(f1) == empty &&
(int) f0->index != yindex) {
f->next = special;
special = f;
} else {
f->next = g;
g = f;
}
f = next;
} /* while there are elements in the collision chain */
} /* for each slot of the x subtable */
/* Mark y nodes with pointers from above x. We mark them by
** changing their index to x.
*/
for (i = 0; i < yslots; i++) {
f = ylist[i];
while (f != NULL) {
if (f->ref != 0) {
f->index = xindex;
}
f = f->next;
} /* while there are elements in the collision chain */
} /* for each slot of the y subtable */
/* Move special nodes to the y list. */
f = special;
while (f != NULL) {
next = f->next;
f1 = cuddT(f);
f11 = cuddT(f1);
cuddT(f) = f11;
cuddSatInc(f11->ref);
f0 = cuddE(f);
cuddSatInc(f0->ref);
f->index = yindex;
/* Insert at the beginning of the list so that it will be
** found first if there is a duplicate. The duplicate will
** eventually be moved or garbage collected. No node
** re-expression will add a pointer to it.
*/
posn = ddHash(f11, f0, yshift);
f->next = ylist[posn];
ylist[posn] = f;
newykeys++;
f = next;
}
/* Take care of the remaining x nodes that must be re-expressed.
** They form a linked list pointed by g.
*/
f = g;
while (f != NULL) {
#ifdef DD_COUNT
table->swapSteps++;
#endif
next = f->next;
/* Find f1, f0, f11, f10, f01, f00. */
f1 = cuddT(f);
if ((int) f1->index == yindex || (int) f1->index == xindex) {
f11 = cuddT(f1); f10 = cuddE(f1);
} else {
f11 = empty; f10 = f1;
}
f0 = cuddE(f);
if ((int) f0->index == yindex || (int) f0->index == xindex) {
f01 = cuddT(f0); f00 = cuddE(f0);
} else {
f01 = empty; f00 = f0;
}
/* Create the new T child. */
if (f01 == empty) {
newf1 = f10;
cuddSatInc(newf1->ref);
} else {
/* Check ylist for triple (yindex, f01, f10). */
posn = ddHash(f01, f10, yshift);
/* For each element newf1 in collision list ylist[posn]. */
newf1 = ylist[posn];
/* Search the collision chain skipping the marked nodes. */
while (newf1 != NULL) {
if (cuddT(newf1) == f01 && cuddE(newf1) == f10 &&
(int) newf1->index == yindex) {
cuddSatInc(newf1->ref);
break; /* match */
}
newf1 = newf1->next;
} /* while newf1 */
if (newf1 == NULL) { /* no match */
newf1 = cuddDynamicAllocNode(table);
if (newf1 == NULL)
goto zddSwapOutOfMem;
newf1->index = yindex; newf1->ref = 1;
cuddT(newf1) = f01;
cuddE(newf1) = f10;
/* Insert newf1 in the collision list ylist[pos];
** increase the ref counts of f01 and f10
*/
newykeys++;
newf1->next = ylist[posn];
ylist[posn] = newf1;
cuddSatInc(f01->ref);
cuddSatInc(f10->ref);
}
}
cuddT(f) = newf1;
/* Do the same for f0. */
/* Create the new E child. */
if (f11 == empty) {
newf0 = f00;
cuddSatInc(newf0->ref);
} else {
/* Check ylist for triple (yindex, f11, f00). */
posn = ddHash(f11, f00, yshift);
/* For each element newf0 in collision list ylist[posn]. */
newf0 = ylist[posn];
while (newf0 != NULL) {
if (cuddT(newf0) == f11 && cuddE(newf0) == f00 &&
(int) newf0->index == yindex) {
cuddSatInc(newf0->ref);
break; /* match */
}
newf0 = newf0->next;
} /* while newf0 */
if (newf0 == NULL) { /* no match */
newf0 = cuddDynamicAllocNode(table);
if (newf0 == NULL)
goto zddSwapOutOfMem;
newf0->index = yindex; newf0->ref = 1;
cuddT(newf0) = f11; cuddE(newf0) = f00;
/* Insert newf0 in the collision list ylist[posn];
** increase the ref counts of f11 and f00.
*/
newykeys++;
newf0->next = ylist[posn];
ylist[posn] = newf0;
cuddSatInc(f11->ref);
cuddSatInc(f00->ref);
}
}
cuddE(f) = newf0;
/* Re-insert the modified f in xlist.
** The modified f does not already exists in xlist.
** (Because of the uniqueness of the cofactors.)
*/
posn = ddHash(newf1, newf0, xshift);
newxkeys++;
f->next = xlist[posn];
xlist[posn] = f;
f = next;
} /* while f != NULL */
/* GC the y layer and move the marked nodes to the x list. */
/* For each node f in ylist. */
for (i = 0; i < yslots; i++) {
previous = NULL;
f = ylist[i];
while (f != NULL) {
next = f->next;
if (f->ref == 0) {
cuddSatDec(cuddT(f)->ref);
cuddSatDec(cuddE(f)->ref);
cuddDeallocNode(table, f);
newykeys--;
if (previous == NULL)
ylist[i] = next;
else
previous->next = next;
} else if ((int) f->index == xindex) { /* move marked node */
if (previous == NULL)
ylist[i] = next;
else
previous->next = next;
f1 = cuddT(f);
cuddSatDec(f1->ref);
/* Check ylist for triple (yindex, f1, empty). */
posn = ddHash(f1, empty, yshift);
/* For each element newf1 in collision list ylist[posn]. */
newf1 = ylist[posn];
while (newf1 != NULL) {
if (cuddT(newf1) == f1 && cuddE(newf1) == empty &&
(int) newf1->index == yindex) {
cuddSatInc(newf1->ref);
break; /* match */
}
newf1 = newf1->next;
} /* while newf1 */
if (newf1 == NULL) { /* no match */
newf1 = cuddDynamicAllocNode(table);
if (newf1 == NULL)
goto zddSwapOutOfMem;
newf1->index = yindex; newf1->ref = 1;
cuddT(newf1) = f1; cuddE(newf1) = empty;
/* Insert newf1 in the collision list ylist[posn];
** increase the ref counts of f1 and empty.
*/
newykeys++;
newf1->next = ylist[posn];
ylist[posn] = newf1;
if (posn == i && previous == NULL)
previous = newf1;
cuddSatInc(f1->ref);
cuddSatInc(empty->ref);
}
cuddT(f) = newf1;
f0 = cuddE(f);
/* Insert f in x list. */
posn = ddHash(newf1, f0, xshift);
newxkeys++;
newykeys--;
f->next = xlist[posn];
xlist[posn] = f;
} else {
previous = f;
}
f = next;
} /* while f */
} /* for i */
/* Set the appropriate fields in table. */
table->subtableZ[x].keys = newxkeys;
table->subtableZ[y].keys = newykeys;
table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys;
/* Update univ section; univ[x] remains the same. */
table->univ[y] = cuddT(table->univ[x]);
#if 0
(void) fprintf(table->out,"x = %d y = %d\n", x, y);
(void) Cudd_DebugCheck(table);
(void) Cudd_CheckKeys(table);
#endif
return (table->keysZ);
zddSwapOutOfMem:
(void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n");
return (0);
} /* end of cuddZddLinearInPlace */
/**Function********************************************************************
Synopsis [Given xLow <= x <= xHigh moves x up and down between the
boundaries.]
Description [Given xLow <= x <= xHigh moves x up and down between the
boundaries. Finds the best position and does the required changes.
Returns 1 if successful; 0 otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
cuddZddLinearAux(
DdManager * table,
int x,
int xLow,
int xHigh)
{
Move *move;
Move *moveUp; /* list of up move */
Move *moveDown; /* list of down move */
int initial_size;
int result;
initial_size = table->keysZ;
#ifdef DD_DEBUG
assert(table->subtableZ[x].keys > 0);
#endif
moveDown = NULL;
moveUp = NULL;
if (x == xLow) {
moveDown = cuddZddLinearDown(table, x, xHigh, NULL);
/* At this point x --> xHigh. */
if (moveDown == (Move *) CUDD_OUT_OF_MEM)
goto cuddZddLinearAuxOutOfMem;
/* Move backward and stop at best position. */
result = cuddZddLinearBackward(table, initial_size, moveDown);
if (!result)
goto cuddZddLinearAuxOutOfMem;
} else if (x == xHigh) {
moveUp = cuddZddLinearUp(table, x, xLow, NULL);
/* At this point x --> xLow. */
if (moveUp == (Move *) CUDD_OUT_OF_MEM)
goto cuddZddLinearAuxOutOfMem;
/* Move backward and stop at best position. */
result = cuddZddLinearBackward(table, initial_size, moveUp);
if (!result)
goto cuddZddLinearAuxOutOfMem;
} else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
moveDown = cuddZddLinearDown(table, x, xHigh, NULL);
/* At this point x --> xHigh. */
if (moveDown == (Move *) CUDD_OUT_OF_MEM)
goto cuddZddLinearAuxOutOfMem;
moveUp = cuddZddUndoMoves(table,moveDown);
#ifdef DD_DEBUG
assert(moveUp == NULL || moveUp->x == x);
#endif
moveUp = cuddZddLinearUp(table, x, xLow, moveUp);
if (moveUp == (Move *) CUDD_OUT_OF_MEM)
goto cuddZddLinearAuxOutOfMem;
/* Move backward and stop at best position. */
result = cuddZddLinearBackward(table, initial_size, moveUp);
if (!result)
goto cuddZddLinearAuxOutOfMem;
} else {
moveUp = cuddZddLinearUp(table, x, xLow, NULL);
/* At this point x --> xHigh. */
if (moveUp == (Move *) CUDD_OUT_OF_MEM)
goto cuddZddLinearAuxOutOfMem;
/* Then move up. */
moveDown = cuddZddUndoMoves(table,moveUp);
#ifdef DD_DEBUG
assert(moveDown == NULL || moveDown->y == x);
#endif
moveDown = cuddZddLinearDown(table, x, xHigh, moveDown);
if (moveDown == (Move *) CUDD_OUT_OF_MEM)
goto cuddZddLinearAuxOutOfMem;
/* Move backward and stop at best position. */
result = cuddZddLinearBackward(table, initial_size, moveDown);
if (!result)
goto cuddZddLinearAuxOutOfMem;
}
while (moveDown != NULL) {
move = moveDown->next;
cuddDeallocMove(table, moveDown);
moveDown = move;
}
while (moveUp != NULL) {
move = moveUp->next;
cuddDeallocMove(table, moveUp);
moveUp = move;
}
return(1);
cuddZddLinearAuxOutOfMem:
if (moveDown != (Move *) CUDD_OUT_OF_MEM) {
while (moveDown != NULL) {
move = moveDown->next;
cuddDeallocMove(table, moveDown);
moveDown = move;
}
}
if (moveUp != (Move *) CUDD_OUT_OF_MEM) {
while (moveUp != NULL) {
move = moveUp->next;
cuddDeallocMove(table, moveUp);
moveUp = move;
}
}
return(0);
} /* end of cuddZddLinearAux */
/**Function********************************************************************
Synopsis [Sifts a variable up applying the XOR transformation.]
Description [Sifts a variable up applying the XOR
transformation. Moves y up until either it reaches the bound (xLow)
or the size of the ZDD heap increases too much. Returns the set of
moves in case of success; NULL if memory is full.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static Move *
cuddZddLinearUp(
DdManager * table,
int y,
int xLow,
Move * prevMoves)
{
Move *moves;
Move *move;
int x;
int size, newsize;
int limitSize;
moves = prevMoves;
limitSize = table->keysZ;
x = cuddZddNextLow(table, y);
while (x >= xLow) {
size = cuddZddSwapInPlace(table, x, y);
if (size == 0)
goto cuddZddLinearUpOutOfMem;
newsize = cuddZddLinearInPlace(table, x, y);
if (newsize == 0)
goto cuddZddLinearUpOutOfMem;
move = (Move *) cuddDynamicAllocNode(table);
if (move == NULL)
goto cuddZddLinearUpOutOfMem;
move->x = x;
move->y = y;
move->next = moves;
moves = move;
move->flags = CUDD_SWAP_MOVE;
if (newsize > size) {
/* Undo transformation. The transformation we apply is
** its own inverse. Hence, we just apply the transformation
** again.
*/
newsize = cuddZddLinearInPlace(table,x,y);
if (newsize == 0) goto cuddZddLinearUpOutOfMem;
#ifdef DD_DEBUG
if (newsize != size) {
(void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize);
}
#endif
} else {
size = newsize;
move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
}
move->size = size;
if ((double)size > (double)limitSize * table->maxGrowth)
break;
if (size < limitSize)
limitSize = size;
y = x;
x = cuddZddNextLow(table, y);
}
return(moves);
cuddZddLinearUpOutOfMem:
while (moves != NULL) {
move = moves->next;
cuddDeallocMove(table, moves);
moves = move;
}
return((Move *) CUDD_OUT_OF_MEM);
} /* end of cuddZddLinearUp */
/**Function********************************************************************
Synopsis [Sifts a variable down and applies the XOR transformation.]
Description [Sifts a variable down. Moves x down until either it
reaches the bound (xHigh) or the size of the ZDD heap increases too
much. Returns the set of moves in case of success; NULL if memory is
full.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static Move *
cuddZddLinearDown(
DdManager * table,
int x,
int xHigh,
Move * prevMoves)
{
Move *moves;
Move *move;
int y;
int size, newsize;
int limitSize;
moves = prevMoves;
limitSize = table->keysZ;
y = cuddZddNextHigh(table, x);
while (y <= xHigh) {
size = cuddZddSwapInPlace(table, x, y);
if (size == 0)
goto cuddZddLinearDownOutOfMem;
newsize = cuddZddLinearInPlace(table, x, y);
if (newsize == 0)
goto cuddZddLinearDownOutOfMem;
move = (Move *) cuddDynamicAllocNode(table);
if (move == NULL)
goto cuddZddLinearDownOutOfMem;
move->x = x;
move->y = y;
move->next = moves;
moves = move;
move->flags = CUDD_SWAP_MOVE;
if (newsize > size) {
/* Undo transformation. The transformation we apply is
** its own inverse. Hence, we just apply the transformation
** again.
*/
newsize = cuddZddLinearInPlace(table,x,y);
if (newsize == 0) goto cuddZddLinearDownOutOfMem;
if (newsize != size) {
(void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize);
}
} else {
size = newsize;
move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
}
move->size = size;
if ((double)size > (double)limitSize * table->maxGrowth)
break;
if (size < limitSize)
limitSize = size;
x = y;
y = cuddZddNextHigh(table, x);
}
return(moves);
cuddZddLinearDownOutOfMem:
while (moves != NULL) {
move = moves->next;
cuddDeallocMove(table, moves);
moves = move;
}
return((Move *) CUDD_OUT_OF_MEM);
} /* end of cuddZddLinearDown */
/**Function********************************************************************
Synopsis [Given a set of moves, returns the ZDD heap to the position
giving the minimum size.]
Description [Given a set of moves, returns the ZDD heap to the
position giving the minimum size. In case of ties, returns to the
closest position giving the minimum size. Returns 1 in case of
success; 0 otherwise.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
cuddZddLinearBackward(
DdManager * table,
int size,
Move * moves)
{
Move *move;
int res;
/* Find the minimum size among moves. */
for (move = moves; move != NULL; move = move->next) {
if (move->size < size) {
size = move->size;
}
}
for (move = moves; move != NULL; move = move->next) {
if (move->size == size) return(1);
if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
if (!res) return(0);
}
res = cuddZddSwapInPlace(table, move->x, move->y);
if (!res)
return(0);
if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) {
res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
if (!res) return(0);
}
}
return(1);
} /* end of cuddZddLinearBackward */
/**Function********************************************************************
Synopsis [Given a set of moves, returns the ZDD heap to the order
in effect before the moves.]
Description [Given a set of moves, returns the ZDD heap to the
order in effect before the moves. Returns 1 in case of success;
0 otherwise.]
SideEffects [None]
******************************************************************************/
static Move*
cuddZddUndoMoves(
DdManager * table,
Move * moves)
{
Move *invmoves = NULL;
Move *move;
Move *invmove;
int size;
for (move = moves; move != NULL; move = move->next) {
invmove = (Move *) cuddDynamicAllocNode(table);
if (invmove == NULL) goto cuddZddUndoMovesOutOfMem;
invmove->x = move->x;
invmove->y = move->y;
invmove->next = invmoves;
invmoves = invmove;
if (move->flags == CUDD_SWAP_MOVE) {
invmove->flags = CUDD_SWAP_MOVE;
size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
if (!size) goto cuddZddUndoMovesOutOfMem;
} else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE;
size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
if (!size) goto cuddZddUndoMovesOutOfMem;
size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
if (!size) goto cuddZddUndoMovesOutOfMem;
} else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */
#ifdef DD_DEBUG
(void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n");
#endif
invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE;
size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
if (!size) goto cuddZddUndoMovesOutOfMem;
size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y);
if (!size) goto cuddZddUndoMovesOutOfMem;
}
invmove->size = size;
}
return(invmoves);
cuddZddUndoMovesOutOfMem:
while (invmoves != NULL) {
move = invmoves->next;
cuddDeallocMove(table, invmoves);
invmoves = move;
}
return((Move *) CUDD_OUT_OF_MEM);
} /* end of cuddZddUndoMoves */

View File

@@ -0,0 +1,278 @@
/**CFile***********************************************************************
FileName [cuddZddMisc.c]
PackageName [cudd]
Synopsis [Miscellaneous utility functions for ZDDs.]
Description [External procedures included in this module:
<ul>
<li> Cudd_zddDagSize()
<li> Cudd_zddCountMinterm()
<li> Cudd_zddPrintSubtable()
</ul>
Internal procedures included in this module:
<ul>
</ul>
Static procedures included in this module:
<ul>
<li> cuddZddDagInt()
</ul>
]
SeeAlso []
Author [Hyong-Kyoon Shin, In-Ho Moon]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include <math.h>
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddZddMisc.c,v 1.18 2012/02/05 01:07:19 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static int cuddZddDagInt (DdNode *n, st_table *tab);
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Counts the number of nodes in a ZDD.]
Description [Counts the number of nodes in a ZDD. This function
duplicates Cudd_DagSize and is only retained for compatibility.]
SideEffects [None]
SeeAlso [Cudd_DagSize]
******************************************************************************/
int
Cudd_zddDagSize(
DdNode * p_node)
{
int i;
st_table *table;
table = st_init_table(st_ptrcmp, st_ptrhash);
i = cuddZddDagInt(p_node, table);
st_free_table(table);
return(i);
} /* end of Cudd_zddDagSize */
/**Function********************************************************************
Synopsis [Counts the number of minterms of a ZDD.]
Description [Counts the number of minterms of the ZDD rooted at
<code>node</code>. This procedure takes a parameter
<code>path</code> that specifies how many variables are in the
support of the function. If the procedure runs out of memory, it
returns (double) CUDD_OUT_OF_MEM.]
SideEffects [None]
SeeAlso [Cudd_zddCountDouble]
******************************************************************************/
double
Cudd_zddCountMinterm(
DdManager * zdd,
DdNode * node,
int path)
{
double dc_var, minterms;
dc_var = (double)((double)(zdd->sizeZ) - (double)path);
minterms = Cudd_zddCountDouble(zdd, node) / pow(2.0, dc_var);
return(minterms);
} /* end of Cudd_zddCountMinterm */
/**Function********************************************************************
Synopsis [Prints the ZDD table.]
Description [Prints the ZDD table for debugging purposes.]
SideEffects [None]
SeeAlso []
******************************************************************************/
void
Cudd_zddPrintSubtable(
DdManager * table)
{
int i, j;
DdNode *z1, *z1_next, *base;
DdSubtable *ZSubTable;
base = table->one;
for (i = table->sizeZ - 1; i >= 0; i--) {
ZSubTable = &(table->subtableZ[i]);
printf("subtable[%d]:\n", i);
for (j = ZSubTable->slots - 1; j >= 0; j--) {
z1 = ZSubTable->nodelist[j];
while (z1 != NIL(DdNode)) {
(void) fprintf(table->out,
#if SIZEOF_VOID_P == 8
"ID = 0x%lx\tindex = %u\tr = %u\t",
(ptruint) z1 / (ptruint) sizeof(DdNode),
z1->index, z1->ref);
#else
"ID = 0x%x\tindex = %hu\tr = %hu\t",
(ptruint) z1 / (ptruint) sizeof(DdNode),
z1->index, z1->ref);
#endif
z1_next = cuddT(z1);
if (Cudd_IsConstant(z1_next)) {
(void) fprintf(table->out, "T = %d\t\t",
(z1_next == base));
}
else {
#if SIZEOF_VOID_P == 8
(void) fprintf(table->out, "T = 0x%lx\t",
(ptruint) z1_next / (ptruint) sizeof(DdNode));
#else
(void) fprintf(table->out, "T = 0x%x\t",
(ptruint) z1_next / (ptruint) sizeof(DdNode));
#endif
}
z1_next = cuddE(z1);
if (Cudd_IsConstant(z1_next)) {
(void) fprintf(table->out, "E = %d\n",
(z1_next == base));
}
else {
#if SIZEOF_VOID_P == 8
(void) fprintf(table->out, "E = 0x%lx\n",
(ptruint) z1_next / (ptruint) sizeof(DdNode));
#else
(void) fprintf(table->out, "E = 0x%x\n",
(ptruint) z1_next / (ptruint) sizeof(DdNode));
#endif
}
z1_next = z1->next;
z1 = z1_next;
}
}
}
putchar('\n');
} /* Cudd_zddPrintSubtable */
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddDagSize.]
Description [Performs the recursive step of Cudd_zddDagSize. Does
not check for out-of-memory conditions.]
SideEffects [None]
SeeAlso []
******************************************************************************/
static int
cuddZddDagInt(
DdNode * n,
st_table * tab)
{
if (n == NIL(DdNode))
return(0);
if (st_is_member(tab, (char *)n) == 1)
return(0);
if (Cudd_IsConstant(n))
return(0);
(void)st_insert(tab, (char *)n, NIL(char));
return(1 + cuddZddDagInt(cuddT(n), tab) +
cuddZddDagInt(cuddE(n), tab));
} /* cuddZddDagInt */

View File

@@ -0,0 +1,381 @@
/**CFile***********************************************************************
FileName [cuddZddPort.c]
PackageName [cudd]
Synopsis [Functions that translate BDDs to ZDDs.]
Description [External procedures included in this module:
<ul>
<li> Cudd_zddPortFromBdd()
<li> Cudd_zddPortToBdd()
</ul>
Internal procedures included in this module:
<ul>
</ul>
Static procedures included in this module:
<ul>
<li> zddPortFromBddStep()
<li> zddPortToBddStep()
</ul>
]
SeeAlso []
Author [Hyong-kyoon Shin, In-Ho Moon]
Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.]
******************************************************************************/
#include "util.h"
#include "cuddInt.h"
/*---------------------------------------------------------------------------*/
/* Constant declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Stucture declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Type declarations */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Variable declarations */
/*---------------------------------------------------------------------------*/
#ifndef lint
static char rcsid[] DD_UNUSED = "$Id: cuddZddPort.c,v 1.14 2012/02/05 01:07:19 fabio Exp $";
#endif
/*---------------------------------------------------------------------------*/
/* Macro declarations */
/*---------------------------------------------------------------------------*/
/**AutomaticStart*************************************************************/
/*---------------------------------------------------------------------------*/
/* Static function prototypes */
/*---------------------------------------------------------------------------*/
static DdNode * zddPortFromBddStep (DdManager *dd, DdNode *B, int expected);
static DdNode * zddPortToBddStep (DdManager *dd, DdNode *f, int depth);
/**AutomaticEnd***************************************************************/
/*---------------------------------------------------------------------------*/
/* Definition of exported functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Converts a BDD into a ZDD.]
Description [Converts a BDD into a ZDD. This function assumes that
there is a one-to-one correspondence between the BDD variables and the
ZDD variables, and that the variable order is the same for both types
of variables. These conditions are established if the ZDD variables
are created by one call to Cudd_zddVarsFromBddVars with multiplicity =
1. Returns a pointer to the resulting ZDD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_zddVarsFromBddVars]
******************************************************************************/
DdNode *
Cudd_zddPortFromBdd(
DdManager * dd,
DdNode * B)
{
DdNode *res;
do {
dd->reordered = 0;
res = zddPortFromBddStep(dd,B,0);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_zddPortFromBdd */
/**Function********************************************************************
Synopsis [Converts a ZDD into a BDD.]
Description [Converts a ZDD into a BDD. Returns a pointer to the resulting
ZDD if successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_zddPortFromBdd]
******************************************************************************/
DdNode *
Cudd_zddPortToBdd(
DdManager * dd,
DdNode * f)
{
DdNode *res;
do {
dd->reordered = 0;
res = zddPortToBddStep(dd,f,0);
} while (dd->reordered == 1);
return(res);
} /* end of Cudd_zddPortToBdd */
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Definition of static functions */
/*---------------------------------------------------------------------------*/
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddPortFromBdd.]
Description []
SideEffects [None]
SeeAlso []
******************************************************************************/
static DdNode *
zddPortFromBddStep(
DdManager * dd,
DdNode * B,
int expected)
{
DdNode *res, *prevZdd, *t, *e;
DdNode *Breg, *Bt, *Be;
int id, level;
statLine(dd);
/* Terminal cases. */
if (B == Cudd_Not(DD_ONE(dd)))
return(DD_ZERO(dd));
if (B == DD_ONE(dd)) {
if (expected >= dd->sizeZ) {
return(DD_ONE(dd));
} else {
return(dd->univ[expected]);
}
}
Breg = Cudd_Regular(B);
/* Computed table look-up. */
res = cuddCacheLookup1Zdd(dd,Cudd_zddPortFromBdd,B);
if (res != NULL) {
level = cuddI(dd,Breg->index);
/* Adding DC vars. */
if (expected < level) {
/* Add suppressed variables. */
cuddRef(res);
for (level--; level >= expected; level--) {
prevZdd = res;
id = dd->invperm[level];
res = cuddZddGetNode(dd, id, prevZdd, prevZdd);
if (res == NULL) {
Cudd_RecursiveDerefZdd(dd, prevZdd);
return(NULL);
}
cuddRef(res);
Cudd_RecursiveDerefZdd(dd, prevZdd);
}
cuddDeref(res);
}
return(res);
} /* end of cache look-up */
if (Cudd_IsComplement(B)) {
Bt = Cudd_Not(cuddT(Breg));
Be = Cudd_Not(cuddE(Breg));
} else {
Bt = cuddT(Breg);
Be = cuddE(Breg);
}
id = Breg->index;
level = cuddI(dd,id);
t = zddPortFromBddStep(dd, Bt, level+1);
if (t == NULL) return(NULL);
cuddRef(t);
e = zddPortFromBddStep(dd, Be, level+1);
if (e == NULL) {
Cudd_RecursiveDerefZdd(dd, t);
return(NULL);
}
cuddRef(e);
res = cuddZddGetNode(dd, id, t, e);
if (res == NULL) {
Cudd_RecursiveDerefZdd(dd, t);
Cudd_RecursiveDerefZdd(dd, e);
return(NULL);
}
cuddRef(res);
Cudd_RecursiveDerefZdd(dd, t);
Cudd_RecursiveDerefZdd(dd, e);
cuddCacheInsert1(dd,Cudd_zddPortFromBdd,B,res);
for (level--; level >= expected; level--) {
prevZdd = res;
id = dd->invperm[level];
res = cuddZddGetNode(dd, id, prevZdd, prevZdd);
if (res == NULL) {
Cudd_RecursiveDerefZdd(dd, prevZdd);
return(NULL);
}
cuddRef(res);
Cudd_RecursiveDerefZdd(dd, prevZdd);
}
cuddDeref(res);
return(res);
} /* end of zddPortFromBddStep */
/**Function********************************************************************
Synopsis [Performs the recursive step of Cudd_zddPortToBdd.]
Description []
SideEffects [None]
SeeAlso []
******************************************************************************/
static DdNode *
zddPortToBddStep(
DdManager * dd /* manager */,
DdNode * f /* ZDD to be converted */,
int depth /* recursion depth */)
{
DdNode *one, *zero, *T, *E, *res, *var;
unsigned int index;
unsigned int level;
statLine(dd);
one = DD_ONE(dd);
zero = DD_ZERO(dd);
if (f == zero) return(Cudd_Not(one));
if (depth == dd->sizeZ) return(one);
index = dd->invpermZ[depth];
level = cuddIZ(dd,f->index);
var = cuddUniqueInter(dd,index,one,Cudd_Not(one));
if (var == NULL) return(NULL);
cuddRef(var);
if (level > (unsigned) depth) {
E = zddPortToBddStep(dd,f,depth+1);
if (E == NULL) {
Cudd_RecursiveDeref(dd,var);
return(NULL);
}
cuddRef(E);
res = cuddBddIteRecur(dd,var,Cudd_Not(one),E);
if (res == NULL) {
Cudd_RecursiveDeref(dd,var);
Cudd_RecursiveDeref(dd,E);
return(NULL);
}
cuddRef(res);
Cudd_RecursiveDeref(dd,var);
Cudd_RecursiveDeref(dd,E);
cuddDeref(res);
return(res);
}
res = cuddCacheLookup1(dd,Cudd_zddPortToBdd,f);
if (res != NULL) {
Cudd_RecursiveDeref(dd,var);
return(res);
}
T = zddPortToBddStep(dd,cuddT(f),depth+1);
if (T == NULL) {
Cudd_RecursiveDeref(dd,var);
return(NULL);
}
cuddRef(T);
E = zddPortToBddStep(dd,cuddE(f),depth+1);
if (E == NULL) {
Cudd_RecursiveDeref(dd,var);
Cudd_RecursiveDeref(dd,T);
return(NULL);
}
cuddRef(E);
res = cuddBddIteRecur(dd,var,T,E);
if (res == NULL) {
Cudd_RecursiveDeref(dd,var);
Cudd_RecursiveDeref(dd,T);
Cudd_RecursiveDeref(dd,E);
return(NULL);
}
cuddRef(res);
Cudd_RecursiveDeref(dd,var);
Cudd_RecursiveDeref(dd,T);
Cudd_RecursiveDeref(dd,E);
cuddDeref(res);
cuddCacheInsert1(dd,Cudd_zddPortToBdd,f,res);
return(res);
} /* end of zddPortToBddStep */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

6776
cudd_local/cudd/doc/cudd.doc Normal file

File diff suppressed because it is too large Load Diff

5036
cudd_local/cudd/doc/cudd.ps Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
<HTML>
<HEAD><TITLE>The cudd package for maintainers</TITLE></HEAD>
<FRAMESET ROWS="5%,90%,5%">
<FRAME SRC="cuddTitle.html">
<FRAMESET COLS="40%,60%">
<FRAME SRC="cuddAllFile.html" NAME="ABSTRACT">
<FRAME SRC="cuddAllDet.html" NAME="MAIN">
</FRAMESET>
<FRAME SRC="credit.html">
</FRAMESET>
</HTML>

View File

@@ -0,0 +1,13 @@
<HTML>
<HEAD><TITLE>The cudd package for maintainers</TITLE></HEAD>
<FRAMESET ROWS="5%,90%,5%">
<FRAME SRC="cuddTitle.html">
<FRAMESET COLS="40%,60%">
<FRAME SRC="cuddAllAbs.html" NAME="ABSTRACT">
<FRAME SRC="cuddAllDet.html" NAME="MAIN">
</FRAMESET>
<FRAME SRC="credit.html">
</FRAMESET>
</HTML>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,33 @@
<HTML>
<HEAD><TITLE>The cudd package: Overview</TITLE></HEAD>
<BODY>
<H1>The cudd package</H1>
<H2>The University of Colorado decision diagram package.</H2>
<H3>By Fabio Somenzi</H3>
<UL>
<LI> <A HREF="cuddExt.html" TARGET="_top">
Information for programmers</A>
<LI> <A HREF="cuddAllByFunc.html" TARGET="_top">
Information for developers sorted by function</A>
<LI> <A HREF="cuddAllByFile.html" TARGET="_top">
Information for developers sorted by file</A>
</UL>
<HR>
External functions and data strucures of the CUDD package.
<ul>
<li> To turn on the gathering of statistics, define DD_STATS.
<li> To link with mis, define DD_MIS.
</ul>
Modified by Abelardo Pardo to interface it to VIS.
<HR>
Last updated on 20120204 17h33
</BODY>
</HTML>
writing ./cuddExt.html

View File

@@ -0,0 +1,14 @@
<HTML>
<HEAD><TITLE>The cudd Package for Programmers</TITLE></HEAD>
<FRAMESET ROWS="5%,90%,5%">
<FRAME SRC="cuddTitle.html">
<FRAMESET COLS="40%,60%">
<FRAME SRC="cuddExtAbs.html" NAME="ABSTRACT">
<FRAME SRC="cuddExtDet.html" NAME="MAIN">
</FRAMESET>
<FRAME SRC="credit.html">
</FRAMESET>
</HTML>
writing ./cuddAllByFunc.html

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
/* Century Schoolbook font is very similar to Computer Modern Math: cmmi */
.MATH { font-family: "Century Schoolbook", serif; }
.MATH I { font-family: "Century Schoolbook", serif; font-style: italic }
.BOLDMATH { font-family: "Century Schoolbook", serif; font-weight: bold }
/* implement both fixed-size and relative sizes */
SMALL.XTINY { font-size : xx-small }
SMALL.TINY { font-size : x-small }
SMALL.SCRIPTSIZE { font-size : smaller }
SMALL.FOOTNOTESIZE { font-size : small }
SMALL.SMALL { }
BIG.LARGE { }
BIG.XLARGE { font-size : large }
BIG.XXLARGE { font-size : x-large }
BIG.HUGE { font-size : larger }
BIG.XHUGE { font-size : xx-large }
/* heading styles */
H1 { }
H2 { }
H3 { }
H4 { }
H5 { }
/* mathematics styles */
DIV.displaymath { } /* math displays */
TD.eqno { } /* equation-number cells */
/* document-specific styles come next */

View File

@@ -0,0 +1,219 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!--Converted with LaTeX2HTML 2008 (1.71)
original version by: Nikos Drakos, CBLU, University of Leeds
* revised and updated by: Marcus Hennecke, Ross Moore, Herb Swan
* with significant contributions from:
Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
<HTML>
<HEAD>
<TITLE>CUDD: CU Decision Diagram Package
Release 2.5.0</TITLE>
<META NAME="description" CONTENT="CUDD: CU Decision Diagram Package
Release 2.5.0">
<META NAME="keywords" CONTENT="cuddIntro">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<META NAME="Generator" CONTENT="LaTeX2HTML v2008">
<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
<LINK REL="STYLESHEET" HREF="cuddIntro.css">
<LINK REL="next" HREF="node1.html">
</HEAD>
<BODY >
<!--Navigation Panel-->
<A NAME="tex2html14"
HREF="node1.html">
<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
SRC="icons/next.png"></A>
<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
SRC="icons/up_g.png">
<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
SRC="icons/prev_g.png">
<A NAME="tex2html12"
HREF="node8.html">
<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
SRC="icons/index.png"></A>
<BR>
<B> Next:</B> <A NAME="tex2html15"
HREF="node1.html">Introduction</A>
&nbsp; <B> <A NAME="tex2html13"
HREF="node8.html">Index</A></B>
<BR>
<BR>
<!--End of Navigation Panel-->
<H1 ALIGN="CENTER">CUDD: CU Decision Diagram Package
<BR>
Release 2.5.0</H1>
<DIV>
<P ALIGN="CENTER"><STRONG>Fabio Somenzi</STRONG></P>
<P ALIGN="CENTER"><I>Department of Electrical, Computer, and Energy Engineering</I></P>
<P ALIGN="LEFT"><SMALL>University of Colorado at Boulder</SMALL></P>
</DIV>
<P>
<BR><HR>
<!--Table of Child-Links-->
<A NAME="CHILD_LINKS"></A>
<UL>
<LI><A NAME="tex2html16"
HREF="node1.html">Introduction</A>
<LI><A NAME="tex2html17"
HREF="node2.html">How to Get CUDD</A>
<UL>
<LI><A NAME="tex2html18"
HREF="node2.html#SECTION00021000000000000000">The CUDD Package</A>
<LI><A NAME="tex2html19"
HREF="node2.html#SECTION00022000000000000000">CUDD Friends</A>
</UL>
<BR>
<LI><A NAME="tex2html20"
HREF="node3.html">User's Manual</A>
<UL>
<LI><A NAME="tex2html21"
HREF="node3.html#SECTION00031000000000000000">Compiling and Linking</A>
<LI><A NAME="tex2html22"
HREF="node3.html#SECTION00032000000000000000">Basic Data Structures</A>
<UL>
<LI><A NAME="tex2html23"
HREF="node3.html#SECTION00032100000000000000">Nodes</A>
<LI><A NAME="tex2html24"
HREF="node3.html#SECTION00032200000000000000">The Manager</A>
<LI><A NAME="tex2html25"
HREF="node3.html#SECTION00032300000000000000">Cache</A>
</UL>
<LI><A NAME="tex2html26"
HREF="node3.html#SECTION00033000000000000000">Initializing and Shutting Down a DdManager</A>
<LI><A NAME="tex2html27"
HREF="node3.html#SECTION00034000000000000000">Setting Parameters</A>
<LI><A NAME="tex2html28"
HREF="node3.html#SECTION00035000000000000000">Constant Functions</A>
<UL>
<LI><A NAME="tex2html29"
HREF="node3.html#SECTION00035100000000000000">One, Logic Zero, and Arithmetic Zero</A>
<LI><A NAME="tex2html30"
HREF="node3.html#SECTION00035200000000000000">Predefined Constants</A>
<LI><A NAME="tex2html31"
HREF="node3.html#SECTION00035300000000000000">Background</A>
<LI><A NAME="tex2html32"
HREF="node3.html#SECTION00035400000000000000">New Constants</A>
</UL>
<LI><A NAME="tex2html33"
HREF="node3.html#SECTION00036000000000000000">Creating Variables</A>
<UL>
<LI><A NAME="tex2html34"
HREF="node3.html#SECTION00036100000000000000">New BDD and ADD Variables</A>
<LI><A NAME="tex2html35"
HREF="node3.html#SECTION00036200000000000000">New ZDD Variables</A>
</UL>
<LI><A NAME="tex2html36"
HREF="node3.html#SECTION00037000000000000000">Basic BDD Manipulation</A>
<LI><A NAME="tex2html37"
HREF="node3.html#SECTION00038000000000000000">Basic ADD Manipulation</A>
<LI><A NAME="tex2html38"
HREF="node3.html#SECTION00039000000000000000">Basic ZDD Manipulation</A>
<LI><A NAME="tex2html39"
HREF="node3.html#SECTION000310000000000000000">Converting ADDs to BDDs and Vice Versa</A>
<LI><A NAME="tex2html40"
HREF="node3.html#SECTION000311000000000000000">Converting BDDs to ZDDs and Vice Versa</A>
<LI><A NAME="tex2html41"
HREF="node3.html#SECTION000312000000000000000">Variable Reordering for BDDs and ADDs</A>
<LI><A NAME="tex2html42"
HREF="node3.html#SECTION000313000000000000000">Grouping Variables</A>
<LI><A NAME="tex2html43"
HREF="node3.html#SECTION000314000000000000000">Variable Reordering for ZDDs</A>
<LI><A NAME="tex2html44"
HREF="node3.html#SECTION000315000000000000000">Keeping Consistent Variable Orders for BDDs and ZDDs</A>
<LI><A NAME="tex2html45"
HREF="node3.html#SECTION000316000000000000000">Hooks</A>
<LI><A NAME="tex2html46"
HREF="node3.html#SECTION000317000000000000000">Timeouts and Limits</A>
<LI><A NAME="tex2html47"
HREF="node3.html#SECTION000318000000000000000">The SIS/VIS Interface</A>
<UL>
<LI><A NAME="tex2html48"
HREF="node3.html#SECTION000318100000000000000">Using the CUDD Package in SIS</A>
</UL>
<LI><A NAME="tex2html49"
HREF="node3.html#SECTION000319000000000000000">Writing Decision Diagrams to a File</A>
<LI><A NAME="tex2html50"
HREF="node3.html#SECTION000320000000000000000">Saving and Restoring BDDs</A>
</UL>
<BR>
<LI><A NAME="tex2html51"
HREF="node4.html">Programmer's Manual</A>
<UL>
<LI><A NAME="tex2html52"
HREF="node4.html#SECTION00041000000000000000">Compiling and Linking</A>
<LI><A NAME="tex2html53"
HREF="node4.html#SECTION00042000000000000000">Reference Counts</A>
<UL>
<LI><A NAME="tex2html54"
HREF="node4.html#SECTION00042100000000000000">NULL Return Values</A>
<LI><A NAME="tex2html55"
HREF="node4.html#SECTION00042200000000000000"><I>Cudd_RecursiveDeref</I> vs. <I>Cudd_Deref</I></A>
<LI><A NAME="tex2html56"
HREF="node4.html#SECTION00042300000000000000">When Increasing the Reference Count is Unnecessary</A>
<LI><A NAME="tex2html57"
HREF="node4.html#SECTION00042400000000000000">Saturating Increments and Decrements</A>
</UL>
<LI><A NAME="tex2html58"
HREF="node4.html#SECTION00043000000000000000">Complement Arcs</A>
<LI><A NAME="tex2html59"
HREF="node4.html#SECTION00044000000000000000">The Cache</A>
<UL>
<LI><A NAME="tex2html60"
HREF="node4.html#SECTION00044100000000000000">Cache Sizing</A>
<LI><A NAME="tex2html61"
HREF="node4.html#SECTION00044200000000000000">Local Caches</A>
</UL>
<LI><A NAME="tex2html62"
HREF="node4.html#SECTION00045000000000000000">The Unique Table</A>
<LI><A NAME="tex2html63"
HREF="node4.html#SECTION00046000000000000000">Allowing Asynchronous Reordering</A>
<LI><A NAME="tex2html64"
HREF="node4.html#SECTION00047000000000000000">Debugging</A>
<LI><A NAME="tex2html65"
HREF="node4.html#SECTION00048000000000000000">Gathering and Interpreting Statistics</A>
<UL>
<LI><A NAME="tex2html66"
HREF="node4.html#SECTION00048100000000000000">Non Modifiable Parameters</A>
<LI><A NAME="tex2html67"
HREF="node4.html#SECTION00048200000000000000">Modifiable Parameters</A>
<LI><A NAME="tex2html68"
HREF="node4.html#SECTION00048300000000000000">Extended Statistics and Reporting</A>
</UL>
<LI><A NAME="tex2html69"
HREF="node4.html#SECTION00049000000000000000">Guidelines for Documentation</A>
</UL>
<BR>
<LI><A NAME="tex2html70"
HREF="node5.html">The C++ Interface</A>
<UL>
<LI><A NAME="tex2html71"
HREF="node5.html#SECTION00051000000000000000">Compiling and Linking</A>
<LI><A NAME="tex2html72"
HREF="node5.html#SECTION00052000000000000000">Basic Manipulation</A>
</UL>
<BR>
<LI><A NAME="tex2html73"
HREF="node6.html">Acknowledgments</A>
<LI><A NAME="tex2html74"
HREF="node7.html">Bibliography</A>
<LI><A NAME="tex2html75"
HREF="node8.html">Index</A>
</UL>
<!--End of Table of Child-Links-->
<BR><HR>
<ADDRESS>
Fabio Somenzi
2012-02-04
</ADDRESS>
</BODY>
</HTML>

View File

@@ -0,0 +1,18 @@
<HTML>
<HEAD><TITLE>The cudd package: Title</TITLE></HEAD>
<BODY>
<TABLE BORDER WIDTH="100%">
<TR>
<TD ALIGN=center> <A HREF="cuddExt.html" TARGET="_top">
Programmer view</A> </TD>
<TD ALIGN=center> <A HREF="cuddAllByFunc.html" TARGET="_top">
Maintainer by function</A> </TD>
<TD ALIGN=center> <A HREF="cuddAllByFile.html" TARGET="_top">
Maintainer by file</A> </TD>
</TR>
</TABLE>
</BODY>
</HTML>
writing ./cuddDesc.html

View File

@@ -0,0 +1,109 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!--Converted with LaTeX2HTML 2008 (1.71)
original version by: Nikos Drakos, CBLU, University of Leeds
* revised and updated by: Marcus Hennecke, Ross Moore, Herb Swan
* with significant contributions from:
Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
<HTML>
<HEAD>
<TITLE>Footnotes</TITLE>
<META NAME="description" CONTENT="Footnotes">
<META NAME="keywords" CONTENT="cuddIntro">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<META NAME="Generator" CONTENT="LaTeX2HTML v2008">
<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
<LINK REL="STYLESHEET" HREF="cuddIntro.css">
<LINK REL="previous" HREF="node7.html">
<LINK REL="up" HREF="cuddIntro.html">
</HEAD>
<BODY >
<DL>
<DT><A NAME="foot139">... application.</A><A
HREF="node3.html#tex2html3"><SUP>1</SUP></A></DT>
<DD>The
global statistical counters are used locally; hence they are
compatible with the use of multiple managers.
<PRE>.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
</PRE>
</DD>
<DT><A NAME="foot1083">...
node.</A><A
HREF="node3.html#tex2html4"><SUP>2</SUP></A></DT>
<DD>When the variables in a group are reordered, the
association between the <I>low</I> field and the index of the first
variable in the group is lost. The package updates the tree to keep
track of the changes. However, the application cannot rely on
<I>low</I> to determine the position of variables.
<PRE>.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
</PRE>
</DD>
</DL>
</BODY>
</HTML>

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Some files were not shown because too many files have changed in this diff Show More