APM: RSMC version 1.0 (not 1.0a) from ipisvn
41
Makefile
Normal 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
@@ -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
|
||||
31
cudd_local/LICENSE
Normal 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
@@ -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
@@ -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
@@ -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
@@ -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
4893
cudd_local/cudd/cuddAPI.c
Normal file
579
cudd_local/cudd/cuddAddAbs.c
Normal 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 */
|
||||
|
||||
941
cudd_local/cudd/cuddAddApply.c
Normal 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>=g; 0 if f<g.]
|
||||
|
||||
Description [Threshold operator for Apply (f if f >=g; 0 if f<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 > g and 0 otherwise.]
|
||||
|
||||
Description [Returns 1 if f > 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 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
316
cudd_local/cudd/cuddAddFind.c
Normal 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 */
|
||||
|
||||
201
cudd_local/cudd/cuddAddInv.c
Normal 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 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
639
cudd_local/cudd/cuddAddIte.c
Normal 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 */
|
||||
290
cudd_local/cudd/cuddAddNeg.c
Normal 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 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
391
cudd_local/cudd/cuddAddWalsh.c
Normal 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 */
|
||||
373
cudd_local/cudd/cuddAndAbs.c
Normal 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 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
814
cudd_local/cudd/cuddAnneal.c
Normal 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
@@ -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
760
cudd_local/cudd/cuddBddAbs.c
Normal 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 */
|
||||
|
||||
515
cudd_local/cudd/cuddBddCorr.c
Normal 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
1016
cudd_local/cudd/cuddBridge.c
Normal file
1053
cudd_local/cudd/cuddCache.c
Normal file
885
cudd_local/cudd/cuddCheck.c
Normal 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
@@ -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
@@ -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 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
1749
cudd_local/cudd/cuddCompose.c
Normal file
2177
cudd_local/cudd/cuddDecomp.c
Normal file
1467
cudd_local/cudd/cuddEssent.c
Normal file
1020
cudd_local/cudd/cuddExact.c
Normal file
1389
cudd_local/cudd/cuddExport.c
Normal file
2178
cudd_local/cudd/cuddGenCof.c
Normal file
960
cudd_local/cudd/cuddGenetic.c
Normal 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
568
cudd_local/cudd/cuddHarwell.c
Normal 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
@@ -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
432
cudd_local/cudd/cuddInteract.c
Normal 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
583
cudd_local/cudd/cuddLevelQ.c
Normal 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
264
cudd_local/cudd/cuddLiteral.c
Normal 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 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
707
cudd_local/cudd/cuddMatMult.c
Normal 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 */
|
||||
2027
cudd_local/cudd/cuddPriority.c
Normal file
517
cudd_local/cudd/cuddRead.c
Normal 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
@@ -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 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
2137
cudd_local/cudd/cuddReorder.c
Normal file
1774
cudd_local/cudd/cuddSat.c
Normal file
318
cudd_local/cudd/cuddSign.c
Normal 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
@@ -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
@@ -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 */
|
||||
1331
cudd_local/cudd/cuddSubsetHB.c
Normal file
1660
cudd_local/cudd/cuddSubsetSP.c
Normal file
1707
cudd_local/cudd/cuddSymmetry.c
Normal file
3213
cudd_local/cudd/cuddTable.c
Normal file
4032
cudd_local/cudd/cuddUtil.c
Normal file
1023
cudd_local/cudd/cuddWindow.c
Normal file
357
cudd_local/cudd/cuddZddCount.c
Normal 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 */
|
||||
1630
cudd_local/cudd/cuddZddFuncs.c
Normal file
1340
cudd_local/cudd/cuddZddGroup.c
Normal file
912
cudd_local/cudd/cuddZddIsop.c
Normal 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 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
971
cudd_local/cudd/cuddZddLin.c
Normal 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 < 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 */
|
||||
|
||||
278
cudd_local/cudd/cuddZddMisc.c
Normal 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 */
|
||||
381
cudd_local/cudd/cuddZddPort.c
Normal 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 */
|
||||
|
||||
1664
cudd_local/cudd/cuddZddReord.c
Normal file
1166
cudd_local/cudd/cuddZddSetop.c
Normal file
1711
cudd_local/cudd/cuddZddSymm.c
Normal file
1205
cudd_local/cudd/cuddZddUtil.c
Normal file
6776
cudd_local/cudd/doc/cudd.doc
Normal file
5036
cudd_local/cudd/doc/cudd.ps
Normal file
3114
cudd_local/cudd/doc/cuddAllAbs.html
Normal file
13
cudd_local/cudd/doc/cuddAllByFile.html
Normal 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>
|
||||
13
cudd_local/cudd/doc/cuddAllByFunc.html
Normal 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>
|
||||
15754
cudd_local/cudd/doc/cuddAllDet.html
Normal file
4876
cudd_local/cudd/doc/cuddAllFile.html
Normal file
33
cudd_local/cudd/doc/cuddDesc.html
Normal 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
|
||||
14
cudd_local/cudd/doc/cuddExt.html
Normal 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
|
||||
1415
cudd_local/cudd/doc/cuddExtAbs.html
Normal file
4450
cudd_local/cudd/doc/cuddExtDet.html
Normal file
30
cudd_local/cudd/doc/cuddIntro.css
Normal 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 */
|
||||
219
cudd_local/cudd/doc/cuddIntro.html
Normal 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>
|
||||
<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>
|
||||
18
cudd_local/cudd/doc/cuddTitle.html
Normal 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
|
||||
109
cudd_local/cudd/doc/footnode.html
Normal 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>
|
||||
BIN
cudd_local/cudd/doc/icons/blueball.png
Normal file
|
After Width: | Height: | Size: 333 B |
BIN
cudd_local/cudd/doc/icons/ch_beg_r.png
Normal file
|
After Width: | Height: | Size: 165 B |
BIN
cudd_local/cudd/doc/icons/ch_begin.png
Normal file
|
After Width: | Height: | Size: 174 B |
BIN
cudd_local/cudd/doc/icons/ch_del_r.png
Normal file
|
After Width: | Height: | Size: 288 B |
BIN
cudd_local/cudd/doc/icons/ch_delet.png
Normal file
|
After Width: | Height: | Size: 288 B |
BIN
cudd_local/cudd/doc/icons/ch_end.png
Normal file
|
After Width: | Height: | Size: 171 B |
BIN
cudd_local/cudd/doc/icons/ch_end_r.png
Normal file
|
After Width: | Height: | Size: 155 B |
BIN
cudd_local/cudd/doc/icons/contents.png
Normal file
|
After Width: | Height: | Size: 278 B |
BIN
cudd_local/cudd/doc/icons/crossref.png
Normal file
|
After Width: | Height: | Size: 147 B |
BIN
cudd_local/cudd/doc/icons/footnote.png
Normal file
|
After Width: | Height: | Size: 190 B |
BIN
cudd_local/cudd/doc/icons/greenball.png
Normal file
|
After Width: | Height: | Size: 333 B |
BIN
cudd_local/cudd/doc/icons/image.png
Normal file
|
After Width: | Height: | Size: 244 B |
BIN
cudd_local/cudd/doc/icons/index.png
Normal file
|
After Width: | Height: | Size: 246 B |
BIN
cudd_local/cudd/doc/icons/next.png
Normal file
|
After Width: | Height: | Size: 245 B |